ошибка C2760: синтаксическая ошибка: неожиданный токен ‘& lt;’, ожидается ‘;’

используя 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: синтаксическая ошибка: неожиданный токен, ожидаемый ‘;’

Вопрос в том, как использовать итератор шаблона.

3

Решение

Во-первых, обратите внимание, что если имеется в виду зависимое имя аргумента шаблона лайк vector<T>::iterator здесь, то вам нужно положить typename до. Кроме того, зависит от того, что T будет компилироваться, только если std::cout«s operator<< принимает это 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;
}

С auto-улучшенный синтаксис C ++ 11, 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, вы можете использовать Диапазон на основе за петля добиться того же, что и в исходном фрагменте:

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 один, так как вы не модифицируете v где-нибудь внутри showset():

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

а затем в нена основе диапазона для цикла версия не забудьте изменить оператор цикла соответственно:

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

Другие решения

Хороший подход к этому выглядит так:

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';
2

По вопросам рекламы [email protected]