2017-03-15 52 views
4

我试图根据模板模板参数是否在其中定义了类型type(例如std::remove_reference具有type成员类型别名),使用SFINAE重载模板类,但我无法想出一个好方法去做这件事。如何检查模板模板类的接口

例如,我想做的事

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

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

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

回答

9

如果我正确地理解了你想要的东西,那么在你的例子中显示的普遍性水平是不可能的。除非知道实例化的参数,否则无法知道模板是否具有类型成员类型别名,因为它可能因专业化而异。例如:

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

template <> 
struct my_trait<double> {}; 

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

它有助于在这样的情况下,要记住,对于不同类型的Tmy_trait<T>所有实例彼此截然不同的类型。类型之间没有实际的关系;它们起源于一个通用模板,它承认编写一个可重用的通用实现的能力,但实例化后的具体类型是完全独立的。

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 { };