STL容器作为模板参数

时间:2013-09-04 12:24:59

标签: c++ templates stl

我正在尝试将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;
}

这是我正在尝试做的事情,因为编译器不能吞下这个吗?

5 个答案:

答案 0 :(得分:14)

您的代码有几个问题,这是一个有效的例子:

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
}

答案 1 :(得分:9)

另一种可能性是使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;
}

答案 2 :(得分:8)

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

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需要一个带有一个类型参数的模板模板参数。

在问题的代码中,Foobar声明中的第一个参数是template <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 to Foobar , the definition of Foobar`需要更改,以便第一个参数采用两个类型参数:

template <template<class, class> TContainer, class TObject> class Foobar { ... };

答案 3 :(得分:0)

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

其次,由于您的模板参数,我猜测

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

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

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

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

我建议您在声明bla

时删除指针类型
Foobar<std::vector, IUnknown> bla( v );
//                  ^^^^^^^^

答案 4 :(得分:0)

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

typedef vector<MyClass> List;

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

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

Foobar<List> variable;