2011-05-17 87 views
9

我給C++ 0x試一試,我在想如何解決出現的下列問題。 我有一個可變參數模板類:類型在可變參數模板參數包中的位置

template<typename... T> 
class MyLovelyClass { 

template<typename SomeType> 
void DoSthWithStorageOfSomeType(); 

private: 
    std::tuple<std::vector<T>...> m_storage; 
}; 

有假設做某種在對應於SOMETYPE模板參數m_storage元組向量操作的(或編譯,如果它不」時失敗的函數T)。 如何做到這一點?

我的想法是在參數包中找到SomeType的索引,然後使用std :: get來獲得合適的向量,但我不知道如何做第一部分。

+0

C++ 14,因此一些標準庫的實現提供'的std ::得到>(m_storage)'。你應該檢查並看看你的是否有這個功能,讓事情變得非常簡單。 – 2015-01-08 21:42:53

回答

7

這裏有一些代碼對元組進行線性搜索,找到第一個類型U,並且在找不到U時會給出編譯時錯誤。請注意,如果元組包含多個U,它只會找到第一個一。不知道這是否是你想要的政策。它將編譯時索引返回到第一個U的元組。也許你可以用它作爲你的std::get的索引。

免責聲明:一起投擲這個答案。只是輕微測試。諸如空元組等邊緣案例有一個可以改進的令人討厭的錯誤消息。等

#include <type_traits> 
#include <tuple> 

template <class Tuple, class T, std::size_t Index = 0> 
struct find_first; 

template <std::size_t Index, bool Valid> 
struct find_first_final_test 
    : public std::integral_constant<std::size_t, Index> 
{ 
}; 

template <std::size_t Index> 
struct find_first_final_test<Index, false> 
{ 
    static_assert(Index == -1, "Type not found in find_first"); 
}; 

template <class Head, class T, std::size_t Index> 
struct find_first<std::tuple<Head>, T, Index> 
    : public find_first_final_test<Index, std::is_same<Head, T>::value> 
{ 
}; 

template <class Head, class ...Rest, class T, std::size_t Index> 
struct find_first<std::tuple<Head, Rest...>, T, Index> 
    : public std::conditional<std::is_same<Head, T>::value, 
        std::integral_constant<std::size_t, Index>, 
        find_first<std::tuple<Rest...>, T, Index+1>>::type 
{ 
}; 

#include <iostream> 

int main() 
{ 
    typedef std::tuple<char, int, short> T; 
    std::cout << find_first<T, double>::value << '\n'; 
} 
+0

謝謝 - 我喜歡它!我可以提出兩點建議:1)將std :: integral_constant 的繼承添加到false情況以避免發現:: value未找到的額外錯誤。 2)爲空元​​組模板添加專門化 struct find_first ,T,Index> :public find_first_final_test { }; – 2011-05-17 15:45:20

+1

我的希望是,您將使用此代碼作爲基礎來準確構建您需要的內容,例如添加您的兩個建議。運行它! :-) – 2011-05-17 16:05:32

+0

好的。謝謝:) – 2011-05-17 17:25:32

1

C++ 14的解決方案:

template <typename T, typename U=void, typename... Types> 
constexpr size_t index() { 
    return std::is_same<T, U>::value ? 0 : 1 + index<T, Types...>(); 
} 

用途:

cout << index<A, Args...>() << "\n"; 
+0

是的,它的段錯誤g ++ 5.4當類型不在列表中(還沒有嘗試過6)。 – 2017-03-14 09:56:23

0

我增加了對 「類型未找到」 情況埃拉扎爾的解決方案的支持,通過返回SIZE_MAX:

template <class T, class F = void, class ...R> 
constexpr size_t TypeIndex() { 
    return is_same<T,F>::value 
     ? 0 
     : is_same<F,void>::value || TypeIndex<T,R...>() == SIZE_MAX 
     ? SIZE_MAX 
     : TypeIndex<T,R...>() + 1; 
} 

編輯:我切換到使用參數包的大小爲「未找到」索引值。這是等的「一個過去的結束」索引或迭代的STL使用,使一個更好的解決方案:

template <class T, class F = void, class ...R> 
constexpr size_t TypeIndex() { 
    return is_same<T,F>::value || is_same<F,void>::value ? 0 : TypeIndex<T,R...>() + 1; 
} 
相關問題