struct VectorOfMaps {
std::tuple<std::map<std::string,double>,
std::map<std::string,int>,
std::map<std::string,short>
> tuple;
};
我想将它概括为一个模板,因此上面的类将由
之类的东西产生VectorOfMaps<3, std::string,double,
std::string,int,
std::string,short>
这可以做类似的事吗?
我知道我可以直接将地图类型放入模板中,但是“std::map
”的重复不会被认为有点难看吗?你觉得怎么样?
(我考虑过是否可以在模板中指定std::pair
类型,但我不确定这些类型是否可以直接用于创建std::map
类型。)
答案 0 :(得分:3)
由于您提到将对的特化传递给类模板:
template<typename... Pairs>
struct VectorOfMaps {
std::tuple<std::map<
typename Pairs::first_type
, typename Pairs::second_type
>...> tuple;
};
这实际上是使用std::pair
作为类型列表 - 您也可以使用类似template<typename T, typename U> struct pair { using first_type = T; using second_type = U; };
的内容。
也可以在没有一对的情况下传递类型,但这需要一些元计算。一个可能的解决方案:
// First argument is accumulator, supposed to be an empty tuple
template<typename Acc, typename... T> struct compute_tuple
{
// Only triggered when the primary template is instantiated, which should
// only happen if sizeof...(T) is odd -- it's possible to assert on that
// instead, too.
static_assert( !sizeof(Acc), "An even number of arguments is required" );
};
// Recursive case
template<typename... Acc, typename First, typename Second, typename... Rest>
struct compute_tuple<std::tuple<Acc...>, First, Second, Rest...>
: compute_tuple<std::tuple<Acc..., std::map<First, Second>>, Rest...> {};
// Terminal case
template<typename Acc>
struct compute_tuple<Acc> { using type = Acc; };
template<typename... T>
struct VectorOfMaps {
/*
* You can assert that sizeof...(T) is even here; it might be more
* helpful than an error deeper inside compute_tuple.
*/
using tuple_type = typename compute_tuple<std::tuple<>, T...>::type;
tuple_type tuple;
};
答案 1 :(得分:2)
first_of_pair元函数是不必要的,因为pair具有first_type和second_type成员。以下是具有可变参数模板参数的解决方案:
template<class... pairtypes>
struct VectorOfMaps
{
std::tuple<
std::map<
typename pairtypes::first_type,
typename pairtypes::second_type
>...
> tuple;
};
int main()
{
VectorOfMaps<
std::pair<int,char>,
std::pair<char,long>
> v;
std::get<0>(v.tuple)[4]='a';
std::get<1>(v.tuple)['z']=5l;
return 0;
}
答案 2 :(得分:0)
如果您可以接受要存储的地图数量的上限,则可以使用不同n值的模板专精来实现:
template<int n, class key0, class value0, class key1 = void, class value1 = void>
struct VectorOfMaps;
template<class key0, class value0>
struct VectorOfMaps<1,key0,value0>
{
// ...
};
template<class key0, class value0, class key1, class value1>
struct VectorOfMaps<2,key0,value0,key1,value1>
{
// ...
};
更好的方法是使用可变参数模板参数。
从一对参数中,您可以使用辅助元函数提取类型:
template<class T>
struct first_of_pair;
template<class First, class Second>
struct first_of_pair<std::pair<First,Second>>
{
typedef First type;
};
// usage in a template where T is an std::pair: typename first_of_pair<T>::type
答案 3 :(得分:0)
我认为使用std :: tuple可以提供更简单,更清晰的方式(但可能会更慢......)。
template<int pos,typename... Args> struct TypeTransformer_ {
using ValueType = typename std::tuple_element<1,std::tuple<Args...>>::type;
using KeyType = typename std::tuple_element<0,std::tuple<Args...>>::type ;
using Type = decltype(std::tuple_cat(std::tuple<std::map<KeyType,ValueType>>(),
typename TypeTransformer_<pos - 2,Args...>::Type()));
};
//Base case with two elements...
template<typename... Args>
struct TypeTransformer_<2,Args...> {
using ValueType = typename std::tuple_element<1,std::tuple<Args...>>::type ;
using KeyType = typename std::tuple_element<0,std::tuple<Args...>>::type ;
using Type = std::tuple<std::map<KeyType,ValueType>> ;
};
//Handling the case of an odd number of parms
template<typename... Args> struct TypeTransformer_<1,Args...> ;
//Nicer interface so we don't have to specify the number of variadic param
template <typename... Args> struct SomeStruct{
using TupleType = typename TypeTransformer_<sizeof...(Args),Args...>::Type;
TupleType tp ;
};