',c++,function"/>

首页 > 解决方案 > 没有匹配 'std::function 的'max' 过载'

问题描述

此代码无法编译,并给出错误:

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.
#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>);
}

我之前使用了一个具有相同参数签名的函数指针,std::function并且有效。这里发生了什么?

标签: c++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; } );

std::max<int>你是说正在使用这 4 个中的一个。

std::function是的,其中只有一个可以与std::function. (请注意,上述两个是无限的可能签名集)。

同时,

int const&(*ptr)(int const&,int const&) = std::max<int>;

在这里,我们正在做重载决议。我们选择std::max<int>需要两个ints 的。

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>);

在这里,我将重载解析延迟到调用传递的可调用对象之后f。那时类型是已知的,所以一切正常。


推荐阅读