SFINAE在std :: enable_if参数内

时间:2017-01-06 15:39:54

标签: c++ c++11 sfinae c++17 enable-if

我有不同的视图类型,每个类型都有std::size_t View::dimension成员常量和typename View::value_type成员类型。

以下编译类型检查应验证FromTo是否为视图(使用is_view<>进行验证),并且From的内容可以分配给{ {1}}。 (相同的维度和可转换的价值类型)。

To
对于任何类型template<typename From, typename To> struct is_compatible_view : std::integral_constant<bool, is_view<From>::value && is_view<To>::value && From::dimension == To::dimension && std::is_convertible<typename From::value_type, typename To::value_type>::value > { };

is_view<T>总是评估为std::true_typestd::false_type。问题是,如果TFrom不是视图类型,则To(例如)可能不存在,From::dimension会导致编译错误。 在这种情况下,它应该评估为is_compatible_view<From, To>

std::false_type用于is_compatible_view的SFINAE,以禁用成员函数。例如,视图类可以具有成员函数

std::enable_if

struct View { constexpr static std::size_t dimension = ... using value_type = ... template<typename Other_view> std::enable_if_t<is_compatible_view<Other_view, View>> assign_from(const Other_view&); void assign_from(const Not_a_view&); }; 不是视图,会导致Not_a_view中的编译错误。调用is_compatible_view<Not_a_view, ...>时,SFINAE不适用,而编译器尝试解析第一个view.assign_from(Not_a_view())函数时会发生编译错误。

如何编写assign_from以使其正常工作?在C ++ 17中,is_compatible_view允许这个吗?

1 个答案:

答案 0 :(得分:4)

一种方法是使用类似std::conditional之类的内容来延迟对类型特征的某些部分的评估,直到我们确认您的类型特征的其他部分已经为真。

那是:

// this one is only valid if From and To are views
template <class From, class To>
struct is_compatible_view_details : std::integral_constant<bool,
    From::dimension == To::dimension &&
    std::is_convertible<typename From::value_type, typename To::value_type>::value
> { };        

// this is the top level one
template<typename From, typename To>
struct is_compatible_view : std::conditional_t<
    is_view<From>::value && is_view<To>::value,
    is_compatible_view_details<From, To>,
    std::false_type>::type
{ };

请注意,我同时使用conditional_t::typeis_compatible_view_details仅在FromTo都是观看时才会被实例化。

类似的方法是使用上面的std::conjunction,因为短路会同样延迟评估:

template <class From, class To>
struct is_compatible_view : std::conjunction_t<
    is_view<From>,
    is_view<To>,
    is_compatible_view_details<From, To>
    >
{ };

无论哪种方式,您都需要提取细节。

第三种方法是使用enable_if_t作为专业化:

template <class From, class To, class = void>
struct is_compatible_view : std::false_type { };

template <class From, class To>
struct is_compatible_view<From, To, std::enable_if_t<
    is_view<From>::value &&
    is_view<To>::value &&
    From::dimension == To::dimension &&
    std::is_convertible<typename From::value_type, typename To::value_type>::value>>
: std::true_type { };

在这里,如果enable_if_t中的任何表达形式不正确,SFINAE就会启动,我们只使用主要模板false_type