13

我正在尝试将 STL 容器作为模板参数传递。在这种情况下,向量。

这是我的非功能代码:

template<template<class> class TContainer, class TObject>
class Foobar
{
public:

    explicit Foobar( TContainer<TObject*> & container )
    :
    container_( container ){}


private:

    TContainer<TObject*> & container_;
};


int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<IUnknown*> v;

    Foobar<std::vector, IUnknown*> bla( v );

    return 0;
}

这是我想要做的事情,因为编译器无法吞下它吗?

4

5 回答 5

19

您的代码有几个问题,这是一个工作示例:

template<template<class, class> class TContainer, class TObject>
class Foobar
{
public:
    explicit Foobar( TContainer<TObject*, std::allocator<TObject*>> & container )
    :
    container_( container ){}

private:
    TContainer<TObject*, std::allocator<TObject*>> & container_;
};

int main()
{
    std::vector<IUnknown*> v;
    Foobar<std::vector, IUnknown> bla( v );
}

您的代码的主要错误是它std::vector需要两个模板参数。看起来像这样template<class T, class Allocator = std::allocator<T>> class vector;。此外,Joachim Pileborg关于双指针问题是正确的,IUnknown**. 但是,您可以使用以下内容简化代码:

template<class TContainer>
class Foobar
{
public:
    explicit Foobar( TContainer & container )
    :
    container_( container ){}

private:
    TContainer & container_; // Be careful with reference members
};

int main()
{
    std::vector<IUnknown*> v;
    Foobar<std::vector<IUnknown*>> bla( v ); // C++11 decltype(v) could be used
}
于 2013-09-04T12:39:09.087 回答
10

另一种可能性是制作TContainer可变参数模板:

#include <vector>

struct TObject {};
struct IUnknown {};

template<template<class...> class TContainer, class TObject>
class Foobar
{
public:
    explicit Foobar( TContainer<TObject*> & container ) : container_( container ){}
private:
    TContainer<TObject*> & container_;
};

int main() {
    std::vector<IUnknown*> v;
    Foobar<std::vector, IUnknown> bla( v );
    return 0;
}
于 2013-09-04T12:48:21.867 回答
9

有三种不同类型的模板参数:值、类型和模板:

template <int value_argument> class C { };
template <class type_argument> class D { };
template <template<classT> class template_argument> class E { };

当您使用这些模板时,您必须提供正确类型的参数:

C<3> c;
D<int> d;
E<C> e;

当您使用第三种形式,即模板模板参数时,作为参数传递的模板必须与模板模板参数的声明相匹配。在我的简单示例中,模板E需要一个接受一个类型参数的模板模板参数。

在问题的代码中,声明中的第一个参数Foobartemplate <class> class TContainer. 在使用它时,传递的模板是std::vector

Foobar<std::vector, IUnknown*> bla(v);

问题是模板模板参数说它应该有一个参数,但作为实际参数传递的模板有两个或更多。正式地,std::vector

template <class T, class Allocator = std::allocator<T>> class vector { ... };

为了使用std::vector> as the first argument toFoobar , the definition ofFoobar` 需要更改,以便第一个参数采用两个类型参数:

template <template<class, class> TContainer, class TObject> class Foobar { ... };
于 2013-09-04T12:47:24.593 回答
0

首先,您可能会遇到一些编译器错误,如果是这样,您应该将它们添加到问题中,因为现在我们只能猜测。

其次,我这是因为你的模板参数:

Foobar<std::vector, IUnknown*> bla( v );
//                  ^^^^^^^^^

在这里你告诉编译器模板参数是一个指针,但是你有构造函数:

Foobar( TContainer<TObject*> & container )
//                 ^^^^^^^^

在构造函数中,您声明containerTContainer带有TObject*成员的,但由于TObject已经是指针,因此您现在有一个指向指针的指针。如果TObject等于IUnknown*TObject*等于IUnknown**。声明container_成员变量时遇到同样的问题。

我建议您在声明时删除指针类型bla

Foobar<std::vector, IUnknown> bla( v );
//                  ^^^^^^^^
于 2013-09-04T12:29:29.320 回答
0

您可以使用 typedef 创建向量类型的同义词以简化编码。

typedef vector<MyClass> List;

然后使用 List 作为模板参数作为“普通”类型。

template<class T, class K>
class Foobar {...}

Foobar<List> variable;
于 2013-09-04T12:29:39.323 回答