我有一个 Writer 结构来做一些序列化
template<typename T>
struct Writer {}; // only specialized version has ::wrap_t
template<>
struct Writer <int> {
typedef int wrap_t;
};
template <typename T>
using Writer_wrap_t = typename Writer<T>::wrap_t;
template<>
struct Writer<float> {
typedef float wrap_t;
};
Run Code Online (Sandbox Code Playgroud)
我想知道一个类型是否有专门的 Writer。代码没有按预期工作:
template<typename T, typename U = Writer_wrap_t <T>>
struct has_writer : std::true_type {};
template<typename T>
struct has_writer<T, void> : std::false_type {};
int main() {
bool b = has_writer <double>::value;
// error C2794: 'wrap_t': is not a member of any direct or indirect base class of 'Writer<T>'
// error C2976: 'has_reflect': too few template arguments
// error C2938: 'Writer_wrap_t ' : Failed to specialize alias template
}
Run Code Online (Sandbox Code Playgroud)
我想那has_writer<double>没有使用专门的版本struct has_writer<T, void> : std::false_type {};?
但是现在第一个替换失败,编译器不应该尝试实例化第二个版本吗?
您没有正确使用 SFINAE。典型的模式是定义一个主模板,其中第二个模板参数是void
template<typename T, typename = void>
struct has_writer : std::false_type {};
Run Code Online (Sandbox Code Playgroud)
然后使用std::void_t您要检查的任何类型作为第二个参数来专门化模板
template<typename T>
struct has_writer<T, std::void_t<Writer_wrap_t <T>>> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
如果您传递给的类型void_t是格式良好的,则选择特化,这是真实的情况,否则选择主要的,这是错误的情况。Writer_wrap_t如果传递给它的类型具有成员 typedef ,则它本身就是格式良好的wrap_t。