有什么方法可以检查模板 class 在 C++14 中是否有嵌套的 class 定义(或类型定义)?

Is there any way to check if a template class has a nested class definition (or a typedef) in C++14?

我定义了以下结构:

struct NoRelationship {};
struct OneToMany      {};
struct Interdependent {};

template <typename RelationType>
struct SignatureGenerator
{
    using type = std::function<void()>;
};

template <>
struct SignatureGenerator<Interdependent>
{
    using type = std::function<void()>;
    using extra_type = std::function<void()>;
};

我需要执行 SFINAE 检查,以确定 class 是否具有“extra_type”定义。我检查了 this and this 个主题,但仍然找不到可行的解决方案。我尝试了后一个主题中的以下代码:

template <typename T>
class has_extra_type
{
    typedef char yes;
    struct no {char x[2];};
    template<typename C> static yes test(decltype(&C::extra_type));
    template<typename C> static no test(...);
public:
    enum { value = sizeof(test<T>(0)) == sizeof (char)};
};

但这不起作用,因为“依赖类型名称之前缺少 'typename'”错误。如果我注释掉一般规范,编译器会告诉我:

//    template<typename C> static no test(...);

错误:没有匹配函数来调用 'test' enum { value = sizeof(test(0)) == sizeof (char)};

注意:候选模板被忽略:替换失败 [with C = SignatureGenerator]:依赖类型名称 'SignatureGenerator::extra_type' 之前缺少 'typename' 模板静态是测试(decltype(&C::extra_type));

关于如何绕过这个的任何想法?

*更新:这是我使用支票的方式:

int main() {
    std::cout << has_extra_type<SignatureGenerator<OneToMany>>::value <<std::endl;
    std::cout << has_extra_type<SignatureGenerator<Interdependent>>::value <<std::endl;
    return 0;
}

它为两个 classes 给出 0,而我希望在第二种情况下检测到 'extra_type'。

对于 yes 重载,您正在使用:

template<typename C> static yes test(decltype(&C::extra_type)); // incorrect for types

但是,decltype& 是必需的,因为您正在查看的示例正在检查是否存在 成员函数 。但是 extra_type 是一种类型,所以你不能获取它的地址,所以该表达式总是格式错误的,并且永远不会选择重载。

由于您要检查 成员类型别名 是否存在,您可以简单地执行以下操作:

template<typename C> static yes test(typename C::extra_type*);

这里是 demo