Когда я объявляю переменную function<void(const Foo&)>
компилятор все еще позволяет мне назначить лямбду, которая принимает значение:
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);
со следующим замечанием:
Этот оператор присваивания не должен участвовать в разрешении перегрузки, если только не decay_t<F> Lvalue-Callable для типов аргументов ArgTypes … и возвращаемого типа R.
где
Вызываемый тип F имеет тип Lvalue-Callable для типов аргументов ArgTypes и возвращает тип R, если выражение INVOKE<р>(declval<F&>(), declval<ArgTypes>() …), рассматриваемый как неоцененный операнд, хорошо сформирован.
Таким образом, вы можете назначить std::function<R(ArgTypes...)>
любая функция, вызываемая с ArgTypes...
и возвращать что-то неявно конвертируемое в R
,
Я не вижу, как предотвратить этот недостаток std::function
в чем-то более ограниченном.
Других решений пока нет …