G++ 编译器错误:无法推断模板参数"_Funct"
g++ compiler error: couldn't deduce template parameter ‘_Funct’
我正在尝试使用ANSI C++for_each语句来迭代并打印标准向量的元素。如果我让for_each调用一个非重载函数,它会起作用,但如果我让它调用一个重载函数,会产生编译器错误。
下面是一个显示编译器错误发生位置的最小测试程序:
#include <algorithm>
#include <iostream>
#include <vector>
struct S {
char c;
int i;
};
std::vector<S> v;
void print_struct(int idx);
void print_struct(const struct S& s);
// f: a non-overloaded version of the preceding function.
void f(const struct S& s);
int main()
{
v.push_back((struct S){'a', 1});
v.push_back((struct S){'b', 2});
v.push_back((struct S){'c', 3});
for (unsigned int i = 0; i < v.size(); ++i)
print_struct(i);
/* ERROR! */
std::for_each(v.begin(), v.end(), print_struct);
/* WORKAROUND: */
std::for_each(v.begin(), v.end(), f);
return 0;
}
// print_struct: Print a struct by its index in vector v.
void print_struct(int idx)
{
std::cout << v[idx].c << ',' << v[idx].i << 'n';
}
// print_struct: Print a struct by reference.
void print_struct(const struct S& s)
{
std::cout << s.c << ',' << s.i << 'n';
}
// f: a non-overloaded version of the preceding function.
void f(const struct S& s)
{
std::cout << s.c << ',' << s.i << 'n';
}
我在openSUSE 12.2中使用编译了这个
g++-4.7 -ansi -Wall for_each.cpp -o for_each
完整的错误消息是:
for_each.cpp: In function ‘int main()’:
for_each.cpp:31:48: error: no matching function for call to ‘for_each(std::vector<S>::iterator, std::vector<S>::iterator, <unresolved overloaded function type>)’
for_each.cpp:31:48: note: candidate is:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from for_each.cpp:5:
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template argument deduction/substitution failed:
for_each.cpp:31:48: note: couldn't deduce template parameter ‘_Funct’
我在Stack Overflow上或在网络上没有看到任何关于这个特定错误的搜索结果。如有任何帮助,我们将不胜感激。
名称指的是一个重载集。您需要指定您想要的过载:
std::for_each(v.begin(), v.end(), (void (&)(S const&)) print_struct);
另一种方法是使用多态可调用函数对象作为助手:
struct PrintStruct
{
template <typename T> void operator()(T const& v) const
{ return print_struct(v); }
};
int main()
{
PrintStruct helper;
std::vector<S> sv;
std::vector<int> iv;
// helper works for both:
std::for_each(sv.begin(), sv.end(), helper);
std::for_each(iv.begin(), iv.end(), helper);
std::for_each
声明如下所示:
template<class InputIter, class Func>
void for_each(InputIter first, InputIter last, Func func);
正如您所看到的,它将任何作为第三个参数。它必须是某个签名的可调用类型或完全是可调用类型,这一点没有限制。
当处理重载函数时,它们本质上是模糊的,除非你给它们一些上下文来选择正确的函数。在对重载函数的调用中,此上下文是您传递的参数。但是,当您需要指针时,您不能将参数用作上下文,并且for_each
参数也不算作上下文,因为它包含任何内容。
作为函数参数可以是选择正确重载的有效上下文的示例,请参见:
// our overloads
void f(int){}
void f(double){}
typedef void (*funcptr_type)(int);
void g(funcptr_type){}
// ...
g(&f); // will select 'void f(int)' overload, since that's
// the only valid one given 'g's parameter
正如您所看到的,您在这里提供了一个清晰的上下文,可以帮助编译器选择正确的重载,而不会使其含糊不清。std::for_each
的参数不会给出这样的上下文,因为它们接受任何内容。
有两种解决方案:
- 手动提供上下文
- 转换为右侧函数指针类型,或者
- 使用正确类型的中间变量并传递
- 使用一个非重载函数,将其分派给一个重载函数(就像您对
f
所做的那样)
注意,在C++11中,您也可以使用lambda作为第二个选项:
std::for_each(v.begin(), v.end(), [](const S& s){ print_struct(s); });
代码上的一些注释:
(struct S){'a', 1}
是一个复合文字,而不是标准C++- C++中不需要
struct S
,只有S
就足够了
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何将enable-if与模板参数和参数包一起使用