2011-05-17 115 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; 
} 
相关问题