我正在尝试使用C ++ 0x,我想知道如何解决出现的以下问题。 我有一个可变参数模板类:
template<typename... T>
class MyLovelyClass {
template<typename SomeType>
void DoSthWithStorageOfSomeType();
private:
std::tuple<std::vector<T>...> m_storage;
};
那里的函数假设对m_storage元组中与SomeType模板参数对应的向量进行某种操作(如果没有,则编译时失败)。 怎么能做到这一点?
我的想法是在参数包中找到SomeType的索引,然后使用std :: get来获取适当的向量,但我不知道如何做第一部分。
答案 0 :(得分: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';
}
答案 1 :(得分:2)
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";
答案 2 :(得分:0)
我添加了对#34;未找到类型的支持&#34;通过返回SIZE_MAX来了解Elazar的解决方案:
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;
}
编辑:我转而使用参数包的大小作为&#34;未找到&#34;指数值。这就像一个过去结束时的STL用法&#34;索引或迭代器,并提供更优雅的解决方案:
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;
}