如果类型`T`有一个`template<> struct Writer<T>`来序列化自身,则为traits

zou*_*yjs 3 c++ templates

我有一个 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 {};

但是现在第一个替换失败,编译器不应该尝试实例化第二个版本吗?

cig*_*ien 5

您没有正确使用 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