如何<>在boost.Hana工作的特点?

时间:2018-06-09 14:52:29

标签: c++ c++14 boost-hana

我对std::enable_if有一些经验。 IIRC,它是关于一个结构良好的表达式导致true返回用户类型T(如果给定)或通过嵌套类型别名返回void。

template<bool,typename = void>
struct enable_if;

template<typename T>
struct enable_if<true,T>{
 using type = T;
};

template <typename T, typename = void>
struct base_template{
     enum { value= false};
};

template <typename T>
struct base_template<T, typename enable_if<std::is_integral<T>::value>::type> {
    enum { value= true};// something useful...
};

struct some{};
static_assert(base_template<some>::value,"F*"); //error: static assertion failed: F
static_assert(base_template<int>::value,"F*");

但是在boost.Hana中,当&lt;&gt;时,我看到了这个特征它的实现就像

template <bool condition>
struct when;

template <typename T, typename = when<true>>
struct base_template{
     enum { value= false};
};

template <typename T>
struct base_template<T, when<std::is_integral<T>::value>> {
    enum { value= true};// something useful...
};

struct some{};

static_assert(base_template<int>::value,"F*");
static_assert(base_template<some>::value,"F*");<source>:28:15: error: static assertion failed: F*

SFINAE如何在这里工作?虽然std::is_integral<some>::value会导致错误,但when<false>ill-formed并不意味着(确实如此?)并且应该将实例化分派给主类模板。我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:2)

这是一般的想法。您可以以基本相同的方式使用enable_if_tdecltype。现在,你可能习惯于看到像这样的SFINAE部分特化:

template<class T, class U = void>
struct Foo {};

template<class T>
struct Foo<T, decltype(T::bar())> {};

... Foo<X> ...

此处,Foo<X>首先由编译器扩展为Foo<X, void>(因为您未在“呼叫网站”处提供U,因此默认U = void为填写而来)。然后,编译器查找类模板Foo的最佳匹配特化。如果decltype(X::bar())实际上是void,那么Foo<T, decltype(T::bar())> [with T=X]将是Foo<X, void>的完美匹配。否则,将使用通用Foo<T, U> [with T=X, U=void]

现在为Hana when示例。

template<bool> struct when {};

template<class T, class U = when<true>>
struct Foo {};

template<class T>
struct Foo<T, when<T::baz>> {};

... Foo<X> ...

此处,Foo<X>首先由编译器扩展为Foo<X, when<true>>(因为您未在“呼叫网站”处提供U,因此默认U = when<true>为填写而来)。然后,编译器查找类模板Foo的最佳匹配特化。如果when<X::baz>实际上是when<true>,那么Foo<T, when<T::baz>> [with T=X]将是Foo<X, when<true>>的完美匹配。否则,将使用通用Foo<T, U> [with T=X, U=when<true>]

您可以将我的示例中的简单表达式T::baz替换为任意复杂的布尔表达式,只要它是constexpr-evaluable即可。在原始示例中,表达式为std::is_integral<T>::value

我的CppCon 2017会话"A Soupçon of SFINAE"介绍了一些类似的例子。