Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可变模板类参数容器实例化_C++_Templates_C++11_Variadic Templates - Fatal编程技术网

C++ 可变模板类参数容器实例化

C++ 可变模板类参数容器实例化,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,我想实例化一个可变模板类Store,它对于targets…包中的每种类型都有一个std::vector template<typename... TArgs> class Store { // obviously not valid code // assuming each type of TArgs... has a `unsigned int` id that can be // retrieved with getId<T>() s

我想实例化一个可变模板类
Store
,它对于
targets…
包中的每种类型都有一个
std::vector

template<typename... TArgs> class Store {
    // obviously not valid code
    // assuming each type of TArgs... has a `unsigned int` id that can be
    // retrieved with getId<T>()
    std::array<sizeof...(TArgs), std::vector<TArgs...>> bags;

    template<typename T> void add(T mValue) { 
        bags[getId<T>()].push_back(mValue); 
    }

    template<typename T> std::vector<T>& get() { 
        return bags[getId<T>()]; 
    }
};
…但这将需要手工编写所有可能的类型组合,并且无法使用用户定义的类型


我相信编译器知道使用可变模板生成类(如
Store
)所需的一切-有没有一种方法可以真正表达这一意图?

以下内容可以满足您的需要:

#include <type_traits>
#include <vector>
#include <tuple>
#include <iostream>

// indices are a classic
template< std::size_t... Ns >
struct indices
{
    using next = indices< Ns..., sizeof...( Ns ) >;
};

template< std::size_t N >
struct make_indices
{
    using type = typename make_indices< N - 1 >::type::next;
};

template<>
struct make_indices< 0 >
{
    using type = indices<>;
};

// we need something to find a type's index within a list of types
template<typename T, typename U, std::size_t=0>
struct index {};

template<typename T, typename... Us, std::size_t N>
struct index<T,std::tuple<T,Us...>,N>
: std::integral_constant<std::size_t, N> {};

template<typename T, typename U, typename... Us, std::size_t N>
struct index<T,std::tuple<U,Us...>,N>
: index<T,std::tuple<Us...>,N+1> {};

// we need a way to remove duplicate types from a list of types
template<typename T,typename I=void> struct unique;

// step 1: generate indices
template<typename... Ts>
struct unique< std::tuple<Ts...>, void >
: unique< std::tuple<Ts...>, typename make_indices<sizeof...(Ts)>::type >
{
};

// step 2: remove duplicates. Note: No recursion here!
template<typename... Ts, std::size_t... Is>
struct unique< std::tuple<Ts...>, indices<Is...> >
{
    using type = decltype( std::tuple_cat( std::declval<
        typename std::conditional<index<Ts,std::tuple<Ts...>>::value==Is,std::tuple<Ts>,std::tuple<>>::type
>()... ) );
};

// a helper to turn Ts... into std::vector<Ts>...
template<typename> struct vectorize;

template<typename... Ts>
struct vectorize<std::tuple<Ts...>>
{
    using type = std::tuple< std::vector<Ts>... >;
};

// now you can easily use it to define your Store
template<typename... Ts> class Store
{
    using Storage = typename vectorize<typename unique<std::tuple<Ts...>>::type>::type;
    Storage storage;

    template<typename T>
    decltype(std::get<index<T,typename unique<std::tuple<Ts...>>::type>::value>(storage))
    slot()
    {
        return std::get<index<T,typename unique<std::tuple<Ts...>>::type>::value>(storage);
    }

public:
    template<typename T> void add(T mValue) { 
        slot<T>().push_back(mValue); 
    }

    template<typename T> std::vector<T>& get() { 
        return slot<T>();
    }    
};

int main()
{
    Store<int,int,double,int,double> store;
    store.add(42);
    store.add(3.1415);
    store.add(21);
    std::cout << store.get<int>().size() << std::endl; 
    std::cout << store.get<double>().size() << std::endl; 
}
#包括
#包括
#包括
#包括
//指数是一个经典
模板<标准::大小\u t。。。Ns>
结构索引
{
使用next=索引;
};
模板
结构生成索引
{
使用type=typename制作索引::type::next;
};
模板
结构生成索引<0>
{
使用类型=指数;
};
//我们需要在类型列表中找到类型的索引
模板
结构索引{};
模板
结构索引
:std::积分_常数{};
模板
结构索引
:索引{};
//我们需要一种从类型列表中删除重复类型的方法
模板结构唯一;
//步骤1:生成索引
模板
结构唯一
:unique
{
};
//步骤2:删除重复项。注意:这里没有递归!
模板
结构唯一
{
使用type=decltype(std::tuple_cat(std::declval<
typename std::conditional::type
>()... ) );
};
//一个助手来转。。。进入std::vector。。。
模板结构矢量化;
模板
结构矢量化
{
使用type=std::tuple;
};
//现在,您可以轻松地使用它来定义您的商店
模板类存储
{
使用Storage=typename向量化::type;
储存;
模板
decltype(标准::获取(存储))
槽()
{
返回std::get(存储);
}
公众:
模板无效添加(T mValue){
插槽();
}
模板std::vector&get(){
返回槽();
}    
};
int main()
{
商店;
添加(42);
存储。添加(3.1415);
添加(21);

std::cout在C++14中,
std::tuple
的元素可以按类型访问,前提是不存在多个相同类型的元素。因此,您应该能够这样编写:

template<typename... TArgs>
struct Store {

    std::tuple<std::vector<TArgs>...> bags;

    template<typename T>
    void add(T mValue) { 
        get<T>().push_back(mValue); 
    }

    template<typename T>
    std::vector<T>& get() { 
        return std::get<std::vector<T>>(bags); 
    }
};
模板
结构存储{
标准:元组袋;
模板
void add(T mValue){
get().向后推_(mValue);
}
模板
std::vector&get(){
返回标准::获取(行李);
}
};

你需要一个
std::tuple
来做这件事,
std::vector
不合适。在这里>
std::array
,模板参数的顺序是错误的。它应该是
std::array
,而不是
std::array
。另外,我认为你需要
std::tuple
,而不是
std::vector
(我不确定)@VittorioRomeo重读您的问题,上面的功能可能比您要求的要多:它只提供一个向量来处理重复类型,因此
Store
的行为与
Store
相同。但是您要求的所有情况也会自动覆盖:)非常感谢。聪明有效的解决方案!看起来很棒,不是吗它适用于C++14:)
template<typename... TArgs>
struct Store {

    std::tuple<std::vector<TArgs>...> bags;

    template<typename T>
    void add(T mValue) { 
        get<T>().push_back(mValue); 
    }

    template<typename T>
    std::vector<T>& get() { 
        return std::get<std::vector<T>>(bags); 
    }
};