【问题标题】:Why can't I create a template function like this? [duplicate]为什么我不能创建这样的模板函数? [复制]
【发布时间】:2013-10-18 07:49:38
【问题描述】:

我试图使用如下辅助函数打印vector<int>

这不起作用 -

template<class T>
void print(const std::vector<T>& v)
{
    std::vector<T>::const_iterator i;
    for (i = v.begin(); i != v.end(); i++)
        std::cout << *i << "  ";
    std::cout << std::endl;
}

编辑:我明白了。

但这有效 -

template<class T>
void print(const std::vector<T>& v)
{
    // changed std::vector<T> to std::vector<int>
    std::vector<int>::const_iterator i;
    for (i = v.begin(); i != v.end(); i++)
        std::cout << *i << "  ";
    std::cout << std::endl;
}

我想问以下问题:

  • 为什么第一个不起作用,第二个起作用?
  • 有哪些替代方法可以为相同的功能编写函数? 附言我不希望在函数内部更改任何元素。我想这可以使用 for_each() 算法来完成。但我不确定如何为其编写谓词。

【问题讨论】:

  • 如果你想使用int,可以将class T替换为typename T
  • 哦,请尝试阅读错误消息。它实际上准确地说明了您必须做些什么来修复它。
  • @arne 老实说,我已经编写大量模板代码已有 4 年了,这是我第一次听到这种区别。我已经学会在任何地方都支持class,因为它不能与表示非类型模板参数的typename 混淆。
  • 恭喜。你截取了文字。
  • 我更喜欢像对待成年人一样对待我的同事,并假设读者知道他们在读什么,即知道classtypename 在这种情况下是可以互换的。如果他们不这样做,他们就没有阅读该代码的业务,并且将重新阅读那本教授模板的书,并且永远不会感到困惑。

标签: c++ templates vector


【解决方案1】:

你应该使用

typename std::vector<T>::const_iterator i;

让它工作(正如编译器在错误消息中告诉你的那样)。

const_iterator 在第一种情况下是依赖于模板的名称,因此您必须使用关键字来消除歧义。

请点击 Joachim Pileborg 评论中的链接以获得良好的解释。

【讨论】:

    【解决方案2】:

    std::vector&lt;T&gt;::const_iterator是依赖名,需要在前面加上typename

    typename std::vector<T>::const_iterator i;
    

    或者直接这样写:

    for (auto it  = v.begin(); it != v.end(); ++it) {
        std::cout << *it << "  ";
    }
    

    或者

    for (auto const& e : v) 
    {
       cout << e << "\n";
    }
    std::cout << std::endl;
    

    什么是依赖名称

    以某种方式依赖于模板参数的名称。当然,任何明确包含模板参数的限定或非限定名称都是依赖的。此外,如果访问运算符左侧的表达式类型取决于模板参数,则由成员访问运算符(. 或 ->)限定的限定名称是依赖的。特别是,this->b 中的 b 在出现在模板中时是一个从属名称。最后,在 ident(x, y, z) 形式的调用中的标识符 ident 当且仅当任何参数表达式具有依赖于模板参数的类型时,它才是依赖名称。

    【讨论】:

    • std::copy(,,std::ostream_iterator(std::cout)) - 有很多方法可以做到这一点,而无需拼出迭代器类型。
    【解决方案3】:
    • 为什么第一个不起作用,第二个起作用?

    因为你忽略了错误

    typename std::vector<T>::const_iterator i;
    ^^^Use typename
    
    • 有哪些替代方法可以为相同的功能编写函数?附言我不希望在函数内部更改任何元素。我想这可以使用 for_each() 算法来完成。但我不确定如何为其编写谓词。
    struct foo{
        void operator()(const int &i) const{
            std::cout<<i<<"  ";
        }
    }
    for_each(v.begin(), v.end(),foo());
    

    【讨论】:

    • 所以第二个有效,因为typename 是在第二个函数中定义的,因为我明确写了type?
    • @mozart 是的,因为第二个你有int 类型元素的向量,所以它是已知的
    猜你喜欢
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 2015-02-09
    • 1970-01-01
    • 2011-10-10
    • 2017-01-12
    相关资源
    最近更新 更多