【问题标题】:STL container as a template parameter [closed]STL容器作为模板参数[关闭]
【发布时间】:2013-09-07 22:57:15
【问题描述】:

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

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

【问题讨论】:

  • @itwasntpete,非常有帮助,谢谢。
  • 我的第一条评论是个玩笑...但是在您的代码中存在很多问题。还传递一个类型 (int) 和一个指定的模板类 (vector) 也是一个设计问题。你可以像here一样开始。
  • 请解释一下为什么它不起作用以及您期望它做什么?
  • 添加到汤姆的评论中,请至少显示第一个编译器错误。有一个投票结束这个问题,但我认为如果你显示该错误并特别询问它,那么问题将保持开放。
  • 你的代码是不言自明的,我想我们可以看到你在做什么

标签: c++ templates stl


【解决方案1】:

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

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&lt;class T, class Allocator = std::allocator&lt;T&gt;&gt; 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
}

【讨论】:

  • 关于简化版,你怎么知道向量中的类型是什么? (假设你想在 Foobar 的 'container_' 上使用 for_each。)
  • @moose: typename TContainer::value_type 会给你向量中的类型。我不确定为什么你会需要 for_each。
  • 如果我将 lambda 函数与 for_each 一起使用,我需要 'TContainer::value_type' 作为 lambda 参数。
【解决方案2】:

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

【讨论】:

  • VS2010 无法编译。似乎 '' 是问题所在。
  • @moose 是的,VS 还不支持可变参数。不过应该在 VS 2013 中工作。
【解决方案3】:

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

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 &lt;class&gt; class TContainer。在使用它的地方,传递的模板是std::vector

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

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

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

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

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

【讨论】:

  • +1 用于解释,但在这种情况下的主要问题是 Foobar 的第一个参数是参数数量错误的模板(2 而不是预期的 1)。跨度>
  • @juanchopanza - gack。你说得对。正在修改...
  • @Pet Becker 几年后我从谷歌来到这里,这个解释仍然很棒!谢谢!只是一个问题,当您提供具有单个模板模板参数template&lt;template&lt;class&gt; class T&gt; 的模板并使用vector 作为实际参数时,根据定义省略其第二种类型可以是默认的,为什么编译器不应该使用它的默认参数和仍然接受传递向量?我很困惑!
【解决方案4】:

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

typedef vector<MyClass> List;

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

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

Foobar<List> variable;

【讨论】:

    【解决方案5】:

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

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

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

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

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

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

    我建议你在声明bla时去掉指针类型:

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

    【讨论】:

    • AFAIK,根据我上面的代码,TObject = IUnknown*.
    • @moose 是的,你在TObject 中添加另一个星号,使TObject*IUnknown** 相同。
    • 对不起,你错了。
    • @moose 然后编辑您的问题 以包含实际错误!否则我们只会在黑暗中跌跌撞撞,胡乱猜测。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多