我有不同的视图类型,每个类型都有std::size_t View::dimension
成员常量和typename View::value_type
成员类型。
以下编译类型检查应验证From
和To
是否为视图(使用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_type
或std::false_type
。问题是,如果T
或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, ...>
时,SFINAE不适用,而编译器尝试解析第一个view.assign_from(Not_a_view())
函数时会发生编译错误。
如何编写assign_from
以使其正常工作?在C ++ 17中,is_compatible_view
允许这个吗?
答案 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
和::type
。 is_compatible_view_details
仅在From
和To
都是观看时才会被实例化。
类似的方法是使用上面的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
。