[英]SFINAE inside std::enable_if argument
我有不同的视图类型,每个类型都有一个std::size_t View::dimension
成员常量,以及一个typename View::value_type
成员类型。
以下编译类型检查应验证From
和To
是否都是视图(使用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
> { };
对于任何类型T
, is_view<T>
总是求值为std::true_type
或std::false_type
。 问题是如果From
或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, ...>
导致编译错误。 调用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
。 只有From
和To
都是视图,才会实例化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.