C++ SFINAE inside std::enable_if参数

C++ SFINAE inside std::enable_if参数,c++,c++11,sfinae,c++17,enable-if,C++,C++11,Sfinae,C++17,Enable If,我有不同的视图类型,每个视图类型都有一个std::size\u t view::dimension成员常量和一个typename视图::value\u type成员类型 以下编译类型检查应验证From和To是否都是视图(使用is\u view进行验证),并且From的内容可以分配给To。(尺寸和可转换值类型相同) Not\u a\u视图不是视图,并在is\u compatible\u视图中导致编译错误。调用view.assign\u from(Not_a\u view())时,SFINAE不适用

我有不同的视图类型,每个视图类型都有一个
std::size\u t view::dimension
成员常量和一个
typename视图::value\u type
成员类型

以下编译类型检查应验证
From
To
是否都是视图(使用
is\u view
进行验证),并且
From
的内容可以分配给
To
。(尺寸和可转换值类型相同)

Not\u a\u视图
不是视图,并在
is\u compatible\u视图
中导致编译错误。调用
view.assign\u from(Not_a\u view())
时,SFINAE不适用,而是在编译器尝试解析第一个
assign\u from
函数时发生编译错误


如何编写
与视图兼容
以使其正常工作?在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
{ };
不管怎样,你都需要了解细节


第三种方法是使用
enable\u 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 { };
模板
结构与视图兼容:std::false\u类型{};
模板
结构是\u兼容的\u视图>
:std::true_type{};

在这里,如果
enable\u if\t
中的任何表达式格式不正确,则SFINAE将启动,我们只使用主模板,即
false\u type

,实际上我没有真正理解第一个代码片段中的
::type
。此外,根据用例的不同,如果兼容视图别名模板只需将
From::value\u type
等中的任何错误拉到即时上下文中,则可以创建
enable\u if\u compatible\u视图
别名模板。
// 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
{ };
template <class From, class To>
struct is_compatible_view : std::conjunction_t<
    is_view<From>,
    is_view<To>,
    is_compatible_view_details<From, To>
    >
{ };
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 { };