此代码无法编译,并给出错误:
test.cpp:12:4: error: no matching function for call to 'func'
func(std::max<int>);
^~~~
test.cpp:4:6: note: candidate function not viable: no overload of 'max' matching 'std::function<const int &(const int &, const int &)>' for 1st argument
void func(std::function<const int &(const int &, const int &)> a)
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
#include<iostream>
#include<functional>
#include <algorithm>
void func(std::function<const int &(const int &, const int &)> a)
// void func(const int &a(const int &, const int &)) //this one works
{
std::cout << a(4,5) << std::endl;
}
int main(int argc, char const *argv[])
{
func(std::max<int>);
}
Run Code Online (Sandbox Code Playgroud)
我以前使用了一个具有相同参数签名的函数指针,std::function并且可以正常工作。这里发生了什么?
std 函数不是函数指针。
模板函数的名称在调用或转换为函数指针时会遇到重载解析。传递给 std 函数时,它不会遇到重载解析。
std::max<int>可以引用多个函数;采用一个初始化列表或两个ints参数的参数,并且每个参数都有带比较器或不带比较器的重载。
对于重载决议,除了其中之一之外的所有内容都被丢弃。没有,结果是模棱两可的。
int x00 = std::max<int>( std::initializer_list<int>{1,2,3,4} )
int x01 = std::max<int>( 2, 4 );
int x10 = std::max<int>( std::initializer_list<int>{1,2,3,4}, [](int a, int b){ return b>a; } )
int x11 = std::max<int>( 2, 4, [](int a, int b){ return b>a; } );
Run Code Online (Sandbox Code Playgroud)
说std::max<int>你是说正在使用这 4 个中的一个。
是的,只有其中一个可以使用std::function,但是调用 的 C++ 语言代码std::function不知道这一点,所以它说结果不明确。(请注意,以上两个是无限的可能签名集)。
同时,
int const&(*ptr)(int const&,int const&) = std::max<int>;
Run Code Online (Sandbox Code Playgroud)
在这里,我们正在做重载解析。我们选择std::max<int>需要两个ints 的。
std::function<int const&(int const&, int const&)> f = std::max<int>;
Run Code Online (Sandbox Code Playgroud)
这里我们不对 进行重载解析std::max。
一个简单的解决方法是:
std::function<int const&(int const&, int const&)> f =
[](auto&&...args)->decltype(auto)
{ return std::max<int>(decltype(args)(args)...); };
Run Code Online (Sandbox Code Playgroud)
我有时写成一个宏
#define RETURNS(...) \
noexcept(noexcept( __VA_ARGS__ )) \
-> decltype( __VA_ARGS__ ) \
{ return __VA_ARGS__; }
#define CALL(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
Run Code Online (Sandbox Code Playgroud)
给我们:
std::function<int const&(int const&, int const&)> f = CALL(std::max<int>);
Run Code Online (Sandbox Code Playgroud)
在这里,我将重载决议延迟到我们调用我们传递的可调用对象之后f。那时类型是已知的,所以一切正常。