我试图理解为什么std::function无法区分重载函数.
#include <functional>
void add(int,int){}
class A {};
void add (A, A){}
int main(){
std::function <void(int, int)> func = add;
}
Run Code Online (Sandbox Code Playgroud)
在上面显示的代码中,function<void(int, int)>只能匹配其中一个功能,但它会失败.为什么会这样?我知道我可以通过使用lambda或函数指针到实际函数然后将函数指针存储在函数中来解决这个问题.但为什么这会失败?关于我想要选择哪个功能的上下文不清楚吗?请帮助我理解为什么这会失败,因为我无法理解为什么在这种情况下模板匹配失败.
我得到的编译错误如下:
test.cpp:10:33: error: no viable conversion from '<overloaded function type>' to
'std::function<void (int, int)>'
std::function <void(int, int)> func = add;
^ ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1266:31: note:
candidate constructor not viable: no overload of 'add' matching
'std::__1::nullptr_t' for 1st argument
_LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1267:5: note:
candidate constructor not viable: no overload of 'add' …Run Code Online (Sandbox Code Playgroud) 为什么在std名称空间未定义的行为中添加名称?
显而易见的答案是"因为标准这样说",例如在C++ 14 [namespace.std] 17.6.4.2.1/1中:
如果C++程序将声明或定义添加到命名空间
std或命名空间中的命名空间std,则除非另有说明,否则C++程序的行为是未定义的....
但是,我真的对这项裁决的原因感兴趣.我当然可以理解添加已经存在的名称的重载std可能会破坏行为; 但为什么添加新的,无关的名称是一个问题?
程序已经可以在std宏内部造成严重破坏,这就是为什么几乎所有标准库实现都必须由所有非公共部分的保留名称(双下划线和起始下划线后跟资本)组成.
我真的会对这样的情况感兴趣:
namespace std
{
int foo(int i)
{ return i * 42; }
}
#include <algorithm> // or one or more other standard library headers
Run Code Online (Sandbox Code Playgroud)
当这是完全合法的,标准库必须应对:
#define foo %%
#include <algorithm> // or one or more other standard library headers
Run Code Online (Sandbox Code Playgroud)
这种未定义行为的基本原理是什么?