2017-01-06 46 views
3

我有不同的查看类型,其中每个类型都有一个std::size_t View::dimension成员常量和一个typename View::value_type成员类型。SFINAE里面std :: enable_if参数

以下编译类型检查应该验证如果两个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 
> { }; 

is_view<T>使得它始终计算为std::true_typestd::false_type,对于任何类型的T。问题是,如果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<...>是否允许这样做?

回答

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。如果FromTo都是视图,则只会实例化is_compatible_view_details


类似的方法是使用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

+0

我其实并没有在你的第一个片段中看到':: type'的点。另外,根据用例,创建一个'enable_if_compatible_view'别名模板就足够了,该模板只将'From :: value_type'等中的任何错误拖入直接上下文中。 –

相关问题