刚才有关于课程模板的问题:
对于下面的代码,该函数运行完全正常,但我很困惑为什么/如何运行fill函数而不给迭代器的类/类型(为什么你不需要提供迭代器类型):
#include <vector>
#include <iostream>
#include <typeinfo>
template<typename Iter>
void fill(Iter first, Iter limit, int value){
while (first != limit) {
*first = value;
++first;
}
}
int main() {
std::vector<int> vec1 {2, 4, 6, 1, 9};
fill(vec1.begin(), vec1.end(), 7);
}
无论如何,我的实际问题如下:
我只想做template <typename Iter, typename A>
,所以我可以在函数中指定值变量的数据类型(而不是必须在函数模板中明确地命名int)
然而,当我尝试fill<int>(...)
这个思路时,该程序根本无法正确编译:
#include <vector>
#include <iostream>
#include <typeinfo>
template<typename Iter, typename A>
void fill(Iter first, Iter limit, A value){
while (first != limit) {
*first = value;
++first;
}
}
int main() {
std::vector<int> vec1 {2, 4, 6, 1, 9};
fill<int>(vec1.begin(), vec1.end(), 7);
}
基本上我很好奇如何更改模板以允许单个fill<datatype of value>(arg1,arg2...)
函数仍然正确接受迭代器而不显式命名它们。
谢谢!
编辑:使用::fill
结束!感谢大家的知识和信息!
答案 0 :(得分:2)
您正在调用第二个功能模板。如果要指定特定的模板参数,则必须在您真正要指定的参数之前指定每个参数。
e.g。
fill<std::vector<int>::iterator, int>(std::begin(vec), std::end(vec), 5);
即便如此,您的代码也无法编译。
你的第二个原型不能编译的原因是因为ADL在fill
命名空间中找到另一个名为std
的函数,该函数与你的原型相同,并且不能决定是否使用你的版本或std
内的版本。要解决这个问题,只需像这样调用fill
:
::fill(vec.begin(), vec.end(), 5);
在全局命名空间中显式调用fill
。
调用函数模板,因为它实际上是一个模板,将用于编译器将要使用的实际函数,或者您将显式实例化。
编译器在调用站点上计算出参数的类型,并根据它调用函数模板的正确实例。
它类似于函数参数重载。
E.g。这样:
template<typename T>
auto fn(T arg){
std::cout << arg << std::endl;
}
auto main() -> int{
fn(1); // compiler sees you pass an int
fn(1.0); // compiler sees you pass a double
}
与此相同:
auto fn(int i){
std::cout << i << std::endl;
}
auto fn(double d){ // heh, double d
std::cout << d << std::endl;
}
auto main() -> int{
fn(1);
fn(1.0);
}
答案 1 :(得分:2)
它不起作用的原因是因为您将第一个模板参数Iter
指定为int
,但它不是迭代器的类型,因此是错误。
您必须指定模板参数,因为如果不这样做,参数依赖查找将找到具有相同签名的std::fill
,并且存在歧义。
你可以做些什么来解决它:
Iter
,您可以指定A
:template<typename A, typename Iter>
std::
):::fill(vec1.begin(), vec1.end(), 7);
答案 2 :(得分:0)
我只是想做模板,所以我可以在函数中指定value变量的数据类型(而不是在函数模板中明确地命名int)
你真正想要的(评论内联):
#include <iterator>
#include <vector>
template<class Iter>
Iter myfill(
// deduce template argument from this
Iter first,
// and this
Iter last,
// std::iterator_traits<>::value_type deduces the value type that the
// iterator is iterating over - i.e. what it's 'pointing at'
// we need typename because iterator_traits<Iter> is dependent on the deduction
// of Iter
const typename std::iterator_traits<Iter>::value_type& v)
{
while (first != last) {
*first++ = v;
}
return first;
}
int main()
{
std::vector<int> v1(20);
myfill(std::begin(v1), std::end(v1), 20);
myfill(std::begin(v1),
std::end(v1),
20.0); // NOTE: conversion will happen at the call site
// myfill<std::vector<int>::iterator> will still be selected
}
答案 3 :(得分:-1)
我想你需要将Iterator也作为参数传递,如
std::vector< int >::iterator
因为模板需要这样做
此外,它将是一个模糊的调用,因为std::vector namespace
中已存在填充方法
你可以做的是将填充方法重命名为myfill并且它有效;)