我是模板功能的新手,无法解决此错误。希望你能帮忙。
#include <iostream>
#include <vector>
/*
* Print to the screen the content of a vector
* Define function template in the header
*/
template <typename T> void print_vector(T& v) {
for(typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
std::cout << *i << ' ';
}
int main() {
std::vector<int> field;
field.resize(12, 1);
/*
for( std::vector<int>::const_iterator i = field.begin(); i != field.end(); ++i)
std::cout << *i << ' ';
*/
print_vector(field);
}
我的代码编译失败时出现了很长的错误消息,我甚至无法插入此处。
error: conversion from ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’ to non-scalar type ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >::const_iterator {aka __gnu_cxx::__normal_iterator<const std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >}’ requested
utility.h:21:59: error: no match for ‘operator!=’ in ‘i != (& v)->std::vector<_Tp, _Alloc>::end<int, std::allocator<int> >()’
utility.h:21:59: note: candidates are:
In file included from /usr/include/x86_64-linux-gnu/c++/4.7/./bits/c++allocator.h:34:0,
from /usr/include/c++/4.7/bits/allocator.h:48,
from /usr/include/c++/4.7/string:43,
from /usr/include/c++/4.7/bits/locale_classes.h:42,
from /usr/include/c++/4.7/bits/ios_base.h:43,
from /usr/include/c++/4.7/ios:43,
from /usr/include/c++/4.7/istream:40,
from /usr/include/c++/4.7/fstream:40,
from utility.h:4:
/usr/include/c++/4.7/ext/new_allocator.h:134:5: note: template<class _Tp> bool __gnu_cxx::operator!=(const __gnu_cxx::new_allocator<_Tp>&, const __gnu_cxx::new_allocator<_Tp>&)
/usr/include/c++/4.7/ext/new_allocator.h:134:5: note: template argument deduction/substitution failed:
utility.h:21:59: note: ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >::const_iterator {aka __gnu_cxx::__normal_iterator<const std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >}’ is not derived from ‘const __gnu_cxx::new_allocator<_Tp>’
答案 0 :(得分:4)
致电时
std::vector<int> field;
...
print_vector(field);
T
1 中的print_vector
是field
的类型,即std::vector<int>
。因此,{/ 1}}
typename std::vector<T>::const_iterator
是for(typename std::vector<T>::const_iterator i = v.begin();
,std::vector<std::vector<int> >::const_iterator
(本身为v.begin()
)不可兑换。使用
std::vector<int>::iterator
代替。
1 也就是说:在本案例的函数模板for(typename T::const_iterator i = v.begin();
中创建的函数中。
答案 1 :(得分:1)
在你的功能中:
template <typename T>
void print_vector(T& v) {
for(typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
std::cout << *i << ' ';
}
T
被推断为std::vector<int>
,因此您尝试将std::vector<int>::iterator
(v.begin()
的结果)转换为std::vector<std::vector<int>>::const_iterator
(类型) i
),这不是有效的转换。
相反,只需创建一个更专业的模板函数:
template <typename T>
void print_vector(std::vector<T>& v) {
// as before
}
答案 2 :(得分:0)
您正确调用了该功能。但是后来你把template-argument(容器的类型)和容器元素类型混淆了。
无论如何,它没有理由不是const
。
因此,它应该是这样的:
template <typename T> void print_vector(const T& v) {
for(typename T::const_iterator i = v.begin(); i != v.end(); ++i)
std::cout << *i << ' ';
}
或者使用标准库和lambdas:
template <typename T> void print_vector(const T& v) {
using std::begin; // Using ADL for begin and end to support raw arrays
using std::end;
std::for_each(begin(v), end(v), [](auto&& x){std::cout<<*i<<' ';});
}
或者使用auto
和range-for-loops(我最喜欢的):
template <typename T> void print_vector(const T& v) {
for(auto&& i : v)
std::cout << *i << ' ';
}
或使用C ++ 1z(预计2017年):
void print_vector(const auto& v) {
for(auto&& i : v)
std::cout << *i << ' ';
}
答案 3 :(得分:0)
如果您希望将std::vector<T>::const_iterator i
传递给任何可迭代的,请将T::const_iterator i
替换为void print_vector(std::vector<T>& v)
,或者如果您希望它仅适用于任何类型的矢量,请使用{{1}}进行适当的专门化。
如果您现在运行替换,您将看到您正在为该类型创建向量的内容提供向量,从而获得向量的向量。
GCC 4.8和4.9也改进了消息并添加了更精确的错误插入符号。 如果你不能移动编译器,这是可以理解的,那么你总是可以将像这样的小片段提供给像ideone.com这样的在线片段。在4.8中,错误很可能更简洁,更易读。
哦,如果您可以访问C ++ 11的功能(我不记得4.7中的内容),您可以自动执行这些类型声明并使用类似cbegin()的内容而不是开始获取类型决定选择const_iterator而不是正常的const_iterator。如果您正在学习模板,并且没有工作环境限制,我强烈建议您转移到C ++ 11和更新的GCC,它将使缓存变得更加容易。