Функция std не является указателем функции.
Имя функции шаблона испытывает разрешение перегрузки при вызове или при приведении к указателю на функцию. Он не имеет разрешения перегрузки при передаче в стандартную функцию.
std::max<int>
может относиться к более чем одной функции; те, которые принимают список инициализаторов или два аргумента int
с, и каждый из них имеет перегрузки, которые принимают компараторы или нет.
С разрешением перегрузки все, кроме одного, отбрасываются. Без этого результат неоднозначен.
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; } );
, сказав, std::max<int>
вы говорите, что используется один из этих 4-х.
И да, только один из них работает с std::function
, но код языка C ++, который вызывает std::function
, не знает этого, поэтому говорит, что результат неоднозначен. (обратите внимание, что два из перечисленного являются бесконечным набором возможных сигнатур).
Между тем,
int const&(*ptr)(int const&,int const&) = std::max<int>;
здесь, мы делаем разрешение перегрузки. Мы выбираем std::max<int>
, который занимает два int
с.
std::function<int const&(int const&, int const&)> f = std::max<int>;
, здесь мы не делаем разрешение перегрузки для std::max
.
. Это легко исправить:
std::function<int const&(int const&, int const&)> f =
[](auto&&...args)->decltype(auto)
{ return std::max<int>(decltype(args)(args)...); };
, который я иногда пишу как макрос
#define RETURNS(...) \
noexcept(noexcept( __VA_ARGS__ )) \
-> decltype( __VA_ARGS__ ) \
{ return __VA_ARGS__; }
#define CALL(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
, давая нам:
std::function<int const&(int const&, int const&)> f = CALL(std::max<int>);
здесь I задержка разрешение перегрузки до тех пор, пока мы вызвать вызываемый объект, который мы передаем f
. На данный момент типы известны, поэтому все работает.