C++11 C++;11标准::函数常量重载模糊
我在一个更大的程序中遇到了一个问题,C++11 C++;11标准::函数常量重载模糊,c++11,overloading,std-function,const-correctness,C++11,Overloading,Std Function,Const Correctness,我在一个更大的程序中遇到了一个问题,g++和clang++ #include <functional> #include <string> struct Foo { Foo(int) {} Foo(std::string) {} operator int () const { return 42; } operator std::string () const { return ""; } void foo(std::funct
g++
和clang++
#include <functional>
#include <string>
struct Foo {
Foo(int) {}
Foo(std::string) {}
operator int () const { return 42; }
operator std::string () const { return ""; }
void foo(std::function<void(Foo&, int)>f);
void foo(std::function<void(const Foo&, int)>f) const; // xxx
void foo(std::function<void(const std::string&, Foo&)>f);
void foo(std::function<void(const std::string&, const Foo&)>f) const;
void bar() const {
this->foo([](const Foo&, int){}); // xxx
}
};
为什么不清楚我要调用哪个版本?如何解决此问题?您可以使构造函数使用
std::string
参数显式。这样编译器就不能从std::string
到Foo进行隐式转换。问题是,当从lambda传递到std::function
对象(尤其是参数类型)时,某些类型信息丢失
更具体地说,例如,一个接受std::function
的函数和另一个接受std::function
的函数对于接受void
lambda的int
参数被认为是同样好的重载
例如
#include <functional>
void foo(std::function<void(int)>f);
void foo(std::function<void(double)>f);
void bar() {
foo([](int){});
}
变通办法
解决方案是显式创建适当的std::function
对象:
this->foo(std::function<void(const Foo&, int)>([](const Foo&, int){}));
this->foo(std::function([](const-foo&,int){});
查看std::function
的构造函数约束。两个命名重载都是允许的。两者都产生用户定义的转换,两者都不比另一个好。@KerrekSB:我不太明白。标记的版本具有相同的std::function参数声明,其他版本则没有。为什么这也被认为是用户定义的转换?您的函数参数是lambda表达式,而不是std::function
类型的表达式。所以您需要一个转换。@6502那么您将继续有一个歧义,除非您可以用其他方法解决它。顺便说一下,我认为隐式转换的需要是一种设计气味,它会使代码更难读和理解。随着我的答案的变化,代码工作了(并且在整个程序中工作)。对C/C++类型进行隐式转换的必要性是必不可少的(基本上是实现一种无类型的值来支持JSON数据,因此隐式/转换是为了使对象更有用)。当然,JSON和C++之间有一种阻抗不匹配,但在这种特殊情况下,我不会称之为气味。你有没有更多的关于这是为什么的信息?我遇到了这个问题,想办法解决这个问题,因为没有太多的信息。”本杰明:对不起,我不是语言律师,我从来没有尝试过实现C++前端。不幸的是,C中的概念被关闭了,因此它们有点“闩上”C++和非常奇怪的对象(例如,每个lambda定义是它自己的唯一类型,即使它有相同的接口)。也许这些缺点是不可避免的,因为语言中的所有其他附加功能。。。
amb2.cpp: In function ‘void bar()’:
amb2.cpp:8:18: error: call of overloaded ‘foo(bar()::<lambda(int)>)’ is ambiguous
foo([](int){});
^
amb2.cpp:4:6: note: candidate: void foo(std::function<void(int)>)
void foo(std::function<void(int)>f);
^
amb2.cpp:5:6: note: candidate: void foo(std::function<void(double)>)
void foo(std::function<void(double)>f);
^
this->foo(std::function<void(const Foo&, int)>([](const Foo&, int){}));