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

时间:2022-02-27 17:04:02

Example, I want to specialize a class to have a member variable that is an stl container, say a vector or a list, so I need something like:

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

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

So I can do:

所以我可以这样做:

Test  t = Test<vector, int>();
t.m_collection<vector<int>> = vector<int>();

But this generates

但这会产生

test.cpp:12: error: `CollectionType' is not a template

3 个解决方案

#1


Why not do it like this?

为什么不这样做呢?

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

Test  t = Test<vector<int> >();
t.m_collection = vector<int>();

If you need the itemtype you can use CollectionType::value_type.

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

EDIT: in response to your question about creating a member function returning the value_type, you do it like this:

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

typename CollectionType::value_type foo();

You add the typename because CollectionType has not been bound to an actual type yet. So there isn't a value_type it could look up.

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

#2


What you want is a template template parameter:

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

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

What we did here is specifying that the first template parameter, i.e. CollectionType, is a type template. Therefore, Test can only be instantiated with a type that is itself a template.

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

However, as @Binary Worrier pointed in the comments, this won't work with STL containers since they have 2 template parameters: one for the elements type, the other one for the type of the allocator used for managing storage allocation (which has a default value).

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

Consequently, you need to change the first template parameter so that it has two parameters:

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

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

But wait, that won't work either! Indeed, CollectionType awaits another parameter, the allocator... So now you have two solutions:

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

1 . Enforce the use of a particular allocator:

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

CollectionType<ItemType, std::allocator<ItemType> > m_collection

2 . Add a template parameter for the allocator to your class:

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

template <template <typename,typename> class CollectionType, 
          class ItemType,
          class Allocator = std::allocator<ItemType> >
class Test
{
public:
    CollectionType<ItemType, Allocator> m_collection;
};

So as you see, you end up with something rather complicated, which seems really twisted to deal with STL containers...

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

My advice: see Greg Rogers' answer for a better approach :)!

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

#3


Comeau online likes this:

Comeau online喜欢这个:

#include <vector>

template <template <class T, class A = std::allocator<T> > class CollectionType, class ItemType>
class Test
{
public:
    CollectionType<ItemType> m_collection;
};

void foo()
{
using std::vector;
Test<vector,int>  t = Test<vector, int>();
t.m_collection = vector<int>();
}

#1


Why not do it like this?

为什么不这样做呢?

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

Test  t = Test<vector<int> >();
t.m_collection = vector<int>();

If you need the itemtype you can use CollectionType::value_type.

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

EDIT: in response to your question about creating a member function returning the value_type, you do it like this:

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

typename CollectionType::value_type foo();

You add the typename because CollectionType has not been bound to an actual type yet. So there isn't a value_type it could look up.

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

#2


What you want is a template template parameter:

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

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

What we did here is specifying that the first template parameter, i.e. CollectionType, is a type template. Therefore, Test can only be instantiated with a type that is itself a template.

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

However, as @Binary Worrier pointed in the comments, this won't work with STL containers since they have 2 template parameters: one for the elements type, the other one for the type of the allocator used for managing storage allocation (which has a default value).

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

Consequently, you need to change the first template parameter so that it has two parameters:

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

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

But wait, that won't work either! Indeed, CollectionType awaits another parameter, the allocator... So now you have two solutions:

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

1 . Enforce the use of a particular allocator:

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

CollectionType<ItemType, std::allocator<ItemType> > m_collection

2 . Add a template parameter for the allocator to your class:

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

template <template <typename,typename> class CollectionType, 
          class ItemType,
          class Allocator = std::allocator<ItemType> >
class Test
{
public:
    CollectionType<ItemType, Allocator> m_collection;
};

So as you see, you end up with something rather complicated, which seems really twisted to deal with STL containers...

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

My advice: see Greg Rogers' answer for a better approach :)!

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

#3


Comeau online likes this:

Comeau online喜欢这个:

#include <vector>

template <template <class T, class A = std::allocator<T> > class CollectionType, class ItemType>
class Test
{
public:
    CollectionType<ItemType> m_collection;
};

void foo()
{
using std::vector;
Test<vector,int>  t = Test<vector, int>();
t.m_collection = vector<int>();
}