2015-12-15 82 views
5

假設我想使用std::conditional來確定類型,如果類型是vector<...>,則返回將是vector<...>::size_type,否則將是int。 (只是一個例子)。是否可以構建lazy_conditional元函數

使用std::conditional一個天真的方式:

template<class V> struct is_vector : std::false_type{}; 
template<class T> struct is_vector<std::vector<T>> : std::true_type{}; 

template<class C> 
using my_size_type = typename std::conditional< 
    not is_vector<C>::value, 
    int, 
    C::size_type // note that this line only makes sense when condition is false 
>::type; 

但是這種失敗,因爲如果C是說doubledouble::size_type會給出一個錯誤,即使是第二個錯誤選項的評估。

所以,我想知道是否有一種lazy_conditional其中的虛假(或第二個虛假)聲明不評估。

我在這裏找到了一些東西:https://stackoverflow.com/a/5317659/225186但我不知道如何使用它我的例子。


注意,我知道如何得到相同的結果,而無需使用std::conditional

template<class V> struct my_size_type{typedef int type;}; 
template<class T> struct my_size_type<std::vector<T>>{typedef std::vector<T>::size_type type;}; 

的問題是,如果有一個lazy_conditional,不知怎的,封裝在std::conditional是短路。


一些審判的錯誤,我設法用意念在https://stackoverflow.com/a/5317659/225186,並獲得該遵循之後。這也使我認爲不可能寫std::lazy_conditional,因爲C::size_type根本不能出現在任何表達式中,所以需要兩步表達式。

template<class C, bool B> struct false_case{ 
    typedef void type; 
}; 
template<class C> struct false_case<C, false>{ 
    typedef typename C::size_type type; 
}; 

template<class C> 
using size_type = typename std::conditional< 
    not is_vector<C>::value, 
    int, 
    typename false_case<C, not is_vector<C>::value>::type 
>::type; 

我甚至無法將它壓縮成一個宏,因爲每種情況都不一樣。

回答

4

您需要一個間接的級別。

template<class T> struct identity { using type = T; }; 

template<class C> 
struct size_type_of : identity<typename C::size_type> { }; 

template<class C> 
using size_type = typename std::conditional<not is_vector<C>::value, 
              identity<int>, 
              size_type_of<C>>::type::type; 

關鍵是耽誤看C::size_type(通過實例size_type_of<C>),直到你知道它有一個。


如果你真的想要做的是「C::size_type如果它存在,否則int」,然後std::experimental::detected_or_t是你的朋友:

template<class C> 
using size_type_t = typename C::size_type; 

template<class C> 
using size_type_or_default = std::experimental::detected_or_t<int, size_type_t, C>; 
+0

好吧,我想它不能被封裝成'lazy_conditional '。無論如何,這也表明免費元函數比成員(有std :: size_type_of :: type而不是依賴於T :: size_type)要好(如自由函數比泛型代碼的成員函數更好)。 – alfC

+0

啊,這是我一遍又一遍發現的東西,最後它是我在這裏做的一樣:http://stackoverflow.com/questions/5839357/detect-operator-support-with-decltype-sfinae/18603716# 18603716 – alfC

+0

關於'detected_or_t'兼容性:http://stackoverflow.com/questions/36418570/what-c​​ompiler-option-library-do-i-need-to-use-detect-or-t-type-trait?noredirect= 1個#comment60486585_36418570 – alfC

相關問題