Почему я могу передать вызывающий значение вызываемый элемент в принимающую ссылку std :: function?

Когда я объявляю переменную function<void(const Foo&)>компилятор все еще позволяет мне назначить лямбду, которая принимает значение:

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

(ср. также http://cpp.sh/5dsp)

Поэтому, когда вызывается обработчик, будет сделана копия. Какой раздел стандарта позволяет это? Есть ли способ, которым я могу пометить клиентский код, что это будет проблемой (что-то вроде static_assert?)?

6

Решение

За [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 в чем-то более ограниченном.

5

Другие решения

Других решений пока нет …