如何正确调用模板函数

How to call a template function correctly?

本文关键字:函数 调用 何正确      更新时间:2023-10-16

我是模板函数的新手,无法处理此错误。希望你能帮忙。

#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>’

当您调用时

std::vector<int> field;
...
print_vector(field);

print_vector1中的Tfieldstd::vector<int>的类型。因此中的typename std::vector<T>::const_iterator

for(typename std::vector<T>::const_iterator i = v.begin();

v.begin()(本身是std::vector<int>::iterator)不可转换到的std::vector<std::vector<int> >::const_iterator。使用

for(typename T::const_iterator i = v.begin();

相反。

1也就是说:在这种情况下,在由函数模板print_vector生成的函数中。

在您的函数中:

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>::iteratorv.begin()的结果)转换为std::vector<std::vector<int>>::const_iteratori的类型),这不是有效的转换。

相反,只需制作一个更专业的模板函数:

 template <typename T>  
 void print_vector(std::vector<T>& v) {
    // as before
 }

如果您想将std::vector<T>::const_iterator i传递给任何可迭代的向量,请将其简单地替换为T::const_iterator i;如果您希望它只针对任何类型的向量,则可以用void print_vector(std::vector<T>& v)适当地专门化它。

如果你现在运行一个替换,你会看到你给了一个向量,创建了一个类型之外的向量,从而得到了向量的向量。

此外,GCC 4.8和4.9改进了消息,并添加了更精确的错误插入符号。如果你不能移动编译器(这是可以理解的),那么你可以随时将这样的小片段提供给ideone.com这样的在线编译器。在4.8中,错误很可能会更加简洁易读。

哦,如果你可以访问C++11的功能(我不记得是什么在4.7中实现的),你可以自动进行这些类型声明,并使用cbegin()之类的东西,而不是开始获取类型解析来选择const_iterator,而不是普通的const_iteror。如果你正在学习模板,并且没有工作环境限制,我强烈建议你使用C++11和更新的GCC,这会让你更容易上手。

您正确地调用了函数。但随后您混淆了模板参数(容器的类型)和容器元素类型。

不管怎样,它没有理由不是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和循环范围(我最喜欢):

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