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

时间:2018-09-18 10:22:31

标签: c++

使用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:语法错误:意外令牌,应为';'

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

2 个答案:

答案 0 :(得分:4)

首先请注意,如果在此处引用vector<T>::iterator之类的template argument dependent name,则需要将typename放在前面。此外,取决于T是什么,只有在std::cout的{​​{1}}接受此operator<<的情况下,这才会编译。例如,这可以正常编译:

T

使用C ++ 11的auto增强语法,可以像这样写#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; } ,然后showset()没用:)

typename

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

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;
}

与租用版本一样,因为您在这里不是指template <typename T> void showset(std::vector<T> v) { for (auto& ref : v) { std::cout << ref; } std::cout << std::endl; } 类型,所以没有iterator的含义。


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

showset()

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

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

答案 1 :(得分: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';