Я не думаю, что это возможно, если не считать смены языка в зависимости от того, как работает назначение.
Когда вы пишете std = wrapper
, это синтаксический сахар для std.operator=(wrapper)
.Мы действительно вызываем эту функцию.Это не похоже на инициализацию, где мы также рассматриваем функции преобразования на более высоком уровне † .В общем, у нас есть function::operator=
опций:
function& operator=( const function& other ); // #1
function& operator=( function&& other ); // #2
function& operator=( std::nullptr_t ); // #3
template< class F > function& operator=( F&& f ); // #4
template< class F > function& operator=( std::reference_wrapper<F> f ); // #5
#3
и #5
нежизнеспособны, #4
означает, что у вас есть соответствующий operator()
и #1
и #2
- оба по одной и той же причине, а также из-за наличия вашей функции преобразования.Но #4
является точным совпадением, тогда как ни #1
, ни #2
не являются, поэтому он выигрывает.Полная остановка.
Единственный способ сделать #2
предпочтительным #4
(что вы действительно хотите) - это сделать #4
не кандидатом.Но единственный способ сделать #4
не кандидатом - это сделать wrapper
не вызываемым.Что делает его ... вовсе не оберткой.
Так что вам здесь в основном не повезло.
† Обратите внимание, что std::function<void()> std = wrapper;
делает то, что вы хотите.