为什么我可以将接受值的可调用对象传递给接受引用的 std::function?

Why can I pass a value-accepting callable to a reference-accepting std::function?

当我声明一个变量 function<void(const Foo&)> 时,编译器仍然让我分配一个接受值的 lambda:

function<void(const Foo&)> handler;
handler = [](Foo f){};

(参见 http://cpp.sh/5dsp

所以当调用处理程序时,将制作一个副本。标准的哪一部分允许这样做?有没有一种方法可以标记客户端代码这将是一个问题(某些 static_assert 之类的?)?

根据 [func.wrap.func.con]

std::function<R(ArgTypes...)>

有一个

template<class F> function& operator=(F&& f);

加上以下备注:

This assignment operator shall not participate in overload resolution unless decay_t<F> is Lvalue-Callable for argument types ArgTypes... and return type R.

哪里

A callable type F is Lvalue-Callable for argument types ArgTypes and return type R if the expression INVOKE<R>(declval<F&>(), declval<ArgTypes>()...), considered as an unevaluated operand, is well formed.

因此您可以将任何可使用 ArgTypes... 调用的函数分配给 std::function<R(ArgTypes...)> 并返回可隐式转换为 R.

的函数

我看不出如何避免将 std::function 包装在更有限的东西中。