您可以使用C++模板指定集合类型和该类型的特化吗?

jus*_*nhj 4 c++ collections templates

例如,我想将一个类专门化为一个成员变量,它是一个stl容器,比如一个向量或一个列表,所以我需要这样的东西:

template <class CollectionType, class ItemType>
class Test
{
public:
    CollectionType<ItemType> m_collection;
};
Run Code Online (Sandbox Code Playgroud)

所以我可以这样做:

Test  t = Test<vector, int>();
t.m_collection<vector<int>> = vector<int>();
Run Code Online (Sandbox Code Playgroud)

但这会产生

test.cpp:12: error: `CollectionType' is not a template
Run Code Online (Sandbox Code Playgroud)

Luc*_*lle 14

你想要的是一个模板模板参数:

template <template <typename> class CollectionType, class ItemType>
class Test
{
public:
    CollectionType<ItemType> m_collection;
};
Run Code Online (Sandbox Code Playgroud)

我们在这里做的是指定第一个模板参数,即CollectionType类型模板.因此,Test只能使用本身就是模板的类型进行实例化.

但是,正如@Binary Worrier在评论中指出的那样,这不适用于STL容器,因为它们有2个模板参数:一个用于元素类型,另一个用于管理存储分配的分配器类型(具有默认值).

因此,您需要更改第一个模板参数,使其具有两个参数:

template <template <typename,typename> class CollectionType, class ItemType>
class Test
{
public:
    CollectionType<ItemType> m_collection;
};
Run Code Online (Sandbox Code Playgroud)

但等等,这也行不通!确实,CollectionType等待另一个参数,分配器...所以现在你有两个解决方案:

1.强制使用特定的分配器:

CollectionType<ItemType, std::allocator<ItemType> > m_collection
Run Code Online (Sandbox Code Playgroud)

2.将分配器的模板参数添加到您的类:

template <template <typename,typename> class CollectionType, 
          class ItemType,
          class Allocator = std::allocator<ItemType> >
class Test
{
public:
    CollectionType<ItemType, Allocator> m_collection;
};
Run Code Online (Sandbox Code Playgroud)

所以如你所见,你最终会得到一些相当复杂的东西,这对于处理STL容器似乎非常麻烦......

我的建议:看看Greg Rogers对更好方法的回答:)!

  • 这不会为我编译(VS 2008),我将在向量上为分配器添加第二种类型,使模板声明为"template <template <typename,typename> class CollectionType,class ItemType>".然后m_collection的声明变成了"CollectionType <ItemType,std :: allocator <ItemType >>"+1,用于指出"模板模板参数",谢谢:) (2认同)

Gre*_*ers 10

为什么不这样做呢?

template <class CollectionType>
class Test
{
public:
    CollectionType m_collection;
};

Test  t = Test<vector<int> >();
t.m_collection = vector<int>();
Run Code Online (Sandbox Code Playgroud)

如果您需要itemtype,您可以使用CollectionType::value_type.

编辑:响应您关于创建返回value_type的成员函数的问题,您可以这样做:

typename CollectionType::value_type foo();
Run Code Online (Sandbox Code Playgroud)

您添加了typename,因为CollectionType尚未绑定到实际类型.所以它没有可以查找的value_type.

  • 您需要在CollectionType :: value_type之前添加typename.处理模板成员时,这是一个常见的错误. (2认同)