如何检查模板模板类的接口

时间:2017-03-15 15:25:04

标签: c++ c++11 templates c++14 template-templates

我试图根据模板模板参数是否在其中定义了type类型来使用SFINAE重载模板类(例如std::remove_reference具有type成员类型别名) ,但我无法找到一个很好的方法来做到这一点。

例如,我想做

template <template <typename...> class Trait>
using EnableIfHasTypeMember = std::void_t<Trait::type>;

template <template <typename...> class Trait, typename OtherStuff,
          EnableIfHasTypeMember<Trait>* = nullptr>
class Something { ... }

但是这给了我一个编译器错误。有什么办法可以检查模板模板参数的界面吗?

2 个答案:

答案 0 :(得分:9)

如果我理解你想要的是什么,那么你在例子中展示的一般性水平是不可能的。您无法知道模板是否具有类型成员类型别名,除非您知道它实例化的参数,因为它可能因特殊化而不同。例如:

template <typename T>
struct my_trait
{
    using type = int;
};

template <>
struct my_trait<double> {};

在这种情况下,您期望EnableIfHasTypeMember如何表现?这就是为什么在实例化之前你无法推断模板的内容。

在这种情况下,请注意,my_trait<T>针对不同类型T 的所有实例化都是彼此不同的类型。类型之间没有实际关系;它们源于一个通用模板,它承认编写一个可重用的通用实现的能力,但实例化后的具体类型是完全独立的。

答案 1 :(得分:1)

@Jason R是正确的,你不能在课程模板级别这样做。

如果您想要检测具有type成员的类模板,则必须提供参数以获取特定类型,以检查成员。

改编an example

// primary template handles types that have no nested ::type member:
template< class, class = std::void_t<> >
struct has_type_member : std::false_type { };

// specialization recognizes types that do have a nested ::type member:
template< class T >
struct has_type_member<T, std::void_t<typename T::type>> : std::true_type { };

// specialization recognizes class templates that do have a nested ::type member:
template< template< class ... > class T, class ... Args >
struct has_type_member<T<Args...>, std::void_t<typename T<Args...>::type>> : std::true_type { };