2017-01-06 66 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'等中的任何錯誤拖入直接上下文中。 –

相關問題