【问题标题】:error C2760: syntax error: unexpected token '<', expected ';'错误 C2760:语法错误:意外标记 '<',预期为 ';'
【发布时间】:2018-09-18 10:22:31
【问题描述】:

使用VS2017和代码:

template <typename T>
void showset(vector<T> v)
{
    for (vector<T>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it;
    }
    cout << endl;
} 

错误是:

错误 C2760:语法错误:意外令牌,预期为 ';'

问题是如何使用模板的迭代器

【问题讨论】:

  • 改用typename vector&lt;T&gt;::iterator it = v.begin();,或auto it = v.begin();
  • 另外,不是通过值传递容器等大对象,而是通过常量引用:void showset(const vector&lt;T&gt;&amp; v)

标签: c++


【解决方案1】:

首先请注意,如果在这里引用template argument dependent name 之类的vector&lt;T&gt;::iterator,则需要将typename 放在前面。此外,取决于T 是什么,只有在std::coutoperator&lt;&lt; 接受这个T 时才会编译。例如,这编译得很好:

#include <iostream>
#include <vector>

template <typename T>
void showset(std::vector<T> v)
{
    for (typename std::vector<T>::iterator it = v.begin(); it != v.end(); it++)
    {
        std::cout << *it;
    }
    std::cout << std::endl;
}

struct foo
{
};

int main()
{
    showset(std::vector<int>{1,2,3});
    //showset(std::vector<foo>{}); // Error: `cout` doesn't take `foo`s.

    return 0;
} 

使用C++11的auto-enhanced语法,showset()可以这样写,然后typename就没用了:)

template <typename T>
void showset(std::vector<T> v)
{
    for (auto it = v.begin(); it != v.end(); it++)
    {
        std::cout << *it;
    }
    std::cout << std::endl;
}

同样从 C++11 开始,您可以使用 range-based for loop 来实现与原始 sn-p 相同的功能:

template <typename T>
void showset(std::vector<T> v)
{
    for (auto& ref : v)
    {
        std::cout << ref;
    }
    std::cout << std::endl;
}

与 lase 版本一样,因为您在这里指的不是 iterator 类型,所以没有什么可以放入 typename 的。


请注意,在这两个版本中,您都使用参数v 的值。因此,您要为每个函数调用复制整个向量。由于问题中给出了代码,因此似乎没有理由这样做,因此您应该通过引用传递它,并将其设置为 const 一个,因为您没有在 @987654342 内的任何地方修改 v @:

void showset(const std::vector<T>& v);

然后在非基于范围的for循环版本中不要忘记相应地更改循环语句:

for (typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++)

【讨论】:

  • @Bllue 如果您想知道为什么不输入using namespace std;,欢迎您阅读in here
【解决方案2】:

最好的方法是这样的:

template <typename T>
void showset(const T& v)
{
    for (auto const &x : v)
    {
        cout << x;
    }
    cout << endl;
}

或者没有范围循环:

template <typename T>
void showset(const T& v)
{
    for (auto it = std::begin(v); it != std::end(v); ++it)
    {
        cout << *it;
    }
    cout << endl;
}


编辑
但我通常使用更复杂的东西。或多或少看起来像这样:
template<typename T>
class LogContainerHelper {
    LogContainerHelper(const T& v
                       size_t maxFront,
                       size_t maxTail)
        : mContainer{ v }
        , mMaxFront{ maxFront }
        , mMaxTail{ maxTail }
    {}

    std::ostream &printTo(std::ostream &out) const {
         // here I usually have something more complex
         // depending on mMaxFront and mMaxTail values, 
         // don't have time to recreate that now
         auto it = std::begin(mContainer);
         auto end = std::end(mContainer);

         out << '[';
         if (it != end) {
            out << *it;
            ++it;
         }
         for (; it != end; ++it)
         {
             out << ", " << *it;
         }
         return out << ']';
    }
private:
    const T &mContainer;
    size_t mMaxFront;
    size_t mMaxTail;
};

template<typename T>
std::ostream &operator <<(std::ostream &out, const LogContainerHelper<T> &helper) {
    return helper.printTo(out);
}

template<typename T>
auto LogContainer(const T& v,
                  size_t maxFront = std::numeric_limits<size_t>::max(),
                  size_t maxTail = 0)
        -> LogContainerHelper<T> {
    return LogContainerHelper<T>{ v, maxFront, maxTail };
}

所以以后我可以这样做:

 cout << "Main containter is: " << LogContainer(v) << '\n';

【讨论】:

  • 这和OP的void showset(vector&lt;T&gt; v)不一样
  • 是的,这是故意的。这更通用,它适用于任何容器。
  • 我同意它更普遍,只是说这种 普遍性 可能不是 OP 的意图。如果需要,限制也是一个特征。至少我没有想到他指定的地方不是这样。
猜你喜欢
  • 1970-01-01
  • 2019-03-27
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2015-05-28
  • 1970-01-01
相关资源
最近更新 更多