繁体   English   中英

SFINAE在std :: enable_if参数内

[英]SFINAE inside std::enable_if argument

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

以下编译类型检查应验证FromTo是否都是视图(使用is_view<>验证),并且From的内容可以分配给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
> { };

对于任何类型Tis_view<T>总是求值为std::true_typestd::false_type 问题是如果FromTo不是视图类型,则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, ...>导致编译错误。 调用view.assign_from(Not_a_view()) ,SFINAE不适用,而编译器尝试解析第一个assign_from函数时会发生编译错误。

如何编写is_compatible_view以使其正常工作? 在C ++ 17中, std::conjunction<...>允许这个吗?

一种方法是使用像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::type 只有FromTo都是视图,才会实例化is_compatible_view_details


类似的方法是使用std::conjunction与上面的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中的任何表达式enable_if_t不正确,SFINAE就会启动,我们只使用主模板,即false_type

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM