检查类T是否具有成员类型成员void_t

Dei*_*Dei 4 c++ templates sfinae c++11 c++14

所以这是代码:

template<typename, typename, typename = void>
struct has_member_type : false_type {};

template<typename T, typename Member>
struct has_member_type<T, Member, void_t<typename T::Member>> : true_type {};

struct foo { using bar = int; };

int main()
{
    std::cout << has_member_type<foo, typename foo::bar>::value;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试检查是否foo有bar类型成员.如果实现没有指定类型成员的名称,它工作正常,但这样的名称硬编码到实现中,这对我不起作用.

说复制的问题并没有接近回答我的问题.正如我在上面的段落中所解释的那样,当类型被硬编码到实现中时,它很好,但是当我从外部指定类型时,我无法使它工作(这是特定的问题).代码编译良好,但产生错误的结果.

Tar*_*ama 6

您的代码不起作用,因为typename foo::bar只是直接解析int,而不是传递一些可用于SFINAE的构造.

一个可能的解决方案是创建一个别名模板,它会告诉你它的类型T::bar,然后将其传递给你的检查器.这是做什么的std::experimental::is_detected.这是一个简化的版本,接近你已经*:

template<typename, template <typename> class, typename = void>
struct is_detected : false_type {};

template<typename T, template <typename> class Op>
struct is_detected<T, Op, void_t<Op<T>>> : true_type {};
Run Code Online (Sandbox Code Playgroud)

然后编写要检测的别名模板:

template <typename T> using bar_t = typename T::bar;
Run Code Online (Sandbox Code Playgroud)

用法如下:

is_detected <foo, bar_t>::value
Run Code Online (Sandbox Code Playgroud)

*:我保持模板参数的方式与示例代码相同,以便您可以轻松比较.翻转它们以便在更通用的上下文中使操作符参数变量更好.它还可以让您更容易迁移到std::experimental::is_detected可用的时间.