模板模板参数 - std :: array的扩展

时间:2015-03-16 20:42:07

标签: c++ templates c++11 stl

我对模板模板参数有疑问:

让我们考虑以下课程:

template<typename T, template<class, class=std::allocator<T> > class UnderlyingContainerType = std::vector>
class MyContainer
{
public:
    T Value1;
    T Value2;
    UnderlyingContainerType<T> Container;

    MyContainer() {}

    /* methods implementation goes here */
};

在这个例子中,MyContainer是一个容器聊天使用底层的STL兼容容器来做任何事情。

将基础容器类型声明为模板模板参数,而不是常规模板参数,允许方便地使用类MyContainer,例如:

    MyContainer<int> MCV; //implicitly using vector
    MyContainer<int, std::list> MCL; //no need to write std::list<int> thanks to the 
                                     //template template parameters

现在,虽然这可以与大多数STL容器完美配合,例如std :: vector,std :: deque,std :: list等等,但它不起作用,例如,使用std: :在c ++ 11中提供的数组。

原因是std :: array具有与vector不同的模板参数签名。具体来说,它们是:

std::vector<class T, class allocator = std::allocator<T> >
std::array<class T, int N>

我的问题是,是否有一种方法可以概括MyContainer类,以便底层容器也可以是std :: array。

我提前感谢你。

2 个答案:

答案 0 :(得分:3)

vectorarray的接口之间的通用性仅限于元素类型。您的容器应该反映出:

template<typename T, template<typename> class underlying_container>
struct container
{
    underlying_container<T> storage;
};

现在使用需要一个小技巧:

template<typename T> using vec = vector<T>;
template<typename T> using arr2 = array<T, 2>;

请注意,与vec不同,vector具有固定的分配器,与arr2不同,array具有固定的大小。

现在用法很简单:

container<int, vec> a;
container<double, arr2> b;

See the example in action.

或者,如果您希望将接口与vector使用的接口匹配,只需为array添加实例化大小的模板别名,并添加未使用的类型参数:

template<typename T, typename> using arr2 = array<T, 2>;

See it in action.

答案 1 :(得分:2)

我不知道如何准确地实现,你想要什么。但如果您不需要能够编写MyContainer<int> MCV;,则可以使用

template<class UnderlyingContainerType, class T = typename UnderlyingContainerType::value_type>
class MyContainer
{
public:
    T Value1;
    T Value2;
    UnderlyingContainerType Container;

    MyContainer() {}

    /* methods implementation goes here */
};


int main() {
    MyContainer<std::vector<int>> MCV{};
    MyContainer<std::array<int, 5>> MCA{};
}

键入的内容不仅仅是MyContainer<int, std::vector> MCV;
当然,您仍然可以为基于矢量的版本添加别名:

template<class T>
using MyContainerV = MyContainer < std::vector<T> > ;