提问人:kmhaug 提问时间:9/26/2023 更新时间:9/28/2023 访问量:33
根据类型特征专门化 C++ 11 模板,同时允许回退其他类型
Specialize C++11 template based on type traits while allowing fallback for other types
问:
我目前正在将几个数据结构序列化为 JSON。
现有的数据结构已经提供了一种基于文本的输出格式,当将特定类型转换为 JSON 的函数尚不存在时,我想将其用作默认格式。
我目前已经完成了回退和几个特定的专业化。由于我使用的 JSON 库已经能够使用像 int、float 等素数,而无需任何额外的工作,我希望这些类型有自己的(通用)专用模板函数。
我目前的主要问题是我无法调用基本原理/原语的函数,但是如果我手动指定类型(),则会调用正确的函数。有什么办法可以解决这个问题吗?编译器在第一行中推断出什么类型?to_json(1)
to_json<int>
我仅限于 C++11。
下面总结了我的基本设置
#include <iostream>
#include <type_traits>
// Should rely on fallback
struct S {
};
// Has specialization
struct R {
};
// Fallback. Should catch everything not caught by the specializations
template <typename T>
void to_json(const T& x);
// Specialization for R
template<>
void to_json(const R& x)
{
std::cout << "For R\n";
}
// Does not work
// Specialization for all fundamentals (e.g. int)
template<typename T>
void to_json(const typename std::enable_if<std::is_fundamental<T>::value, T>::type& x)
{
std::cout << "For fundamentals\n";
}
template <typename T>
void to_json(const T& x)
{
std::cout << "General\n";
}
int main()
{
to_json(1); // General. (WRONG, expected fundamentals)
to_json<int>(1); // fundamentals (CORRECT)
to_json(R{}); // R (CORRECT)
to_json(S{}); // General (CORRECT)
return 0;
}
输出:
General
For fundamentals
For R
General
答:
1赞
billz
9/28/2023
#1
您的正向声明模板函数将捕获所有类型。当用混凝土类型初始化时,它会带来麻烦。
//// Fallback. Should catch everything not caught by the specializations
//template <typename T>
//void to_json(const T& x);
下面的代码应该可以正常工作:
// Should rely on fallback
struct S {
};
// Has specialization
struct R {
};
// note: also use enable_if_t to exclude fundamental type
// otherwise compiler is still confused by the redefinition
template <typename T,
std::enable_if_t<!std::is_fundamental<T>::value, bool> = true>
void to_json(const T& x)
{
std::cout << "General\n";
}
// Specialization for R
template<>
void to_json(const R& x)
{
std::cout << "For R\n";
}
// Specialization for all fundamentals (e.g. int)
template<typename T,
std::enable_if_t<std::is_fundamental<T>::value, bool> = true>
void to_json(const T& x)
{
std::cout << "For fundamentals\n";
}
int main()
{
to_json(1); // General. (WRONG, expected fundamentals)
to_json<int>(1); // fundamentals (CORRECT)
to_json(R{}); // R (CORRECT)
to_json(S{}); // General (CORRECT)
return 0;
}
评论
0赞
kmhaug
9/29/2023
谢谢你的解决方案!但是,它不使用 C++11(即 C++14)进行编译。如果我们写例如.如果此重写有任何(已知的)不良副作用,请告诉我。enable_if_t
std::enable_if<std::is_fundamental<T>::value>::type* = nullptr
0赞
kmhaug
10/2/2023
更正:可能是一个更好的解决方案typename std::enable_if<std::is_fundamental<T>::value, bool>::type=true
评论
to_json
T