У меня есть две перегрузки функции foo
, которые принимают разные std::function
, что приводит к проблеме неоднозначности для последнего при использовании с результатом std::bind
. Я не понимаю, почему только это двусмысленно.
void foo(std::function<void(int)>) {}
void foo(std::function<int()>) {}
void take_int(int) { }
int ret_int() { return 0; }
При использовании int()
с функцией bind
я получаю ошибку неоднозначности
foo(std::bind(ret_int)); // ERROR
С ошибкой gcc-5.1 (и аналогичной с clang)
error: call to 'foo' is ambiguous
foo(std::bind(ret_int));
^~~
note: candidate function
void foo(std::function<void(int)>) {}
^
note: candidate function
void foo(std::function<int()>) {}
Однако все последующие работы
foo(std::bind(take_int, _1));
foo(take_int);
foo(ret_int);
foo([](){ return ret_int(); });
struct TakeInt {
void operator()(int) const { }
};
struct RetInt {
int operator()() const { return 0; }
};
foo(TakeInt{});
foo(RetInt{});
Глядя на конструктор std::function
template< class F >
function( F f );
для меня было бы разумным, чтобы любая функция с несколькими перегрузками для разных типов std::function
имела двусмысленность, но это только проблема с вызовом для привязки. Затем я подумал: «Может быть, при обработке типов функций и лямбда-выражений происходит какое-то волшебство, и оно не имеет отношения к реальным классам», но оно также обрабатывает и их.
В en.cppreference есть примечание, в котором говорится [начиная с С++ 14]
Этот конструктор не участвует в разрешении перегрузки, если f не является Callable для типов аргументов Args... и возвращает тип R.