Неоднозначность в перегрузке конструктора из-за std::function

Я хочу сделать две перегрузки конструктора некоторого класса следующим образом:

foo(int, std::function<int(Tpoint, Tpoint)>);
foo(int, std::function<int(Tpoint, Tpoint, std::vector<Tpoint>)>);

При звонке у меня возникла проблема неоднозначности. Зачем?

foo<cv::Point> bar(2,[](cv::Point const& l, cv::Point const& r){
    return 5;
});

Не ясно, что мне нужен первый конструктор, поскольку он имеет только 2 аргумента для std::function,

РЕДАКТИРОВАТЬ:

Как комментирует Lol4t0, он работает на другом компиляторе. Кажется, проблема VS.NET. Пример 1, Пример 2

Я использую Microsoft Visual Studio 2013. Кто-нибудь может воспроизвести?

1 ответ

Решение

MSVC 2013 std::function это только C++11 std::function без дополнительной функции от (если я правильно помню) отчета о дефектах.

Эта дополнительная особенность заключается в том, что template<class F> function(F&&) конструктор должен быть похожим на SFINAE и работать только с типами F такой, что function на самом деле может быть построен из этого типа. (стандарт не требует реализации на основе SFINAE)

В результате, std::function имеет конструктор "попробуй построить из чего угодно". И когда это терпит неудачу, это терпит неудачу слишком поздно для разрешения перегрузки. По крайней мере, в MSVC2013. Так что оба ваших std::functionЭто похоже на допустимые перегрузки.

Я считаю, что последняя версия 2015 года имеет std::function с ограниченной способностью выполнять запрошенную вами перегрузку.

В 2013 году вы можете сделать обходной путь, который может сработать, но это боль.

Во-первых, научитесь делать перегрузки наборов функциональных объектов. Затем создайте набор перегрузки для функционального объекта F и другой функциональный объект, который принимает Tpoint, Tpoint и возвращается some_special_tag_type, Теперь пройдите Tpoint, Tpoint для этого набора перегрузки, и отслеживать, если тип возвращаемого значения some_special_tag_type, Отправка тегов по этому решению от foo(int, F&&) перегрузить в foo_impl(tag_1, int, std::function<blah_1>) и foo_impl(tag_2, int, std::function<blah_2>),

Вероятно, проще просто перейти на MSVC2015 или не полагаться на перегрузку.

Обратите внимание, что этот метод действительно жизнеспособен, если вы перегружаете возвращаемые типы, а не типы аргументов. Это сложно, потому что даже MSVC2015 не имеет "выражения SFINAE", которое наносит вред этому метапрограммированию.

Другие вопросы по тегам