Неоднозначность в перегрузке конструктора из-за 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", которое наносит вред этому метапрограммированию.