我想对某个类的构造函数进行两次重载,如下所示:
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;
});
我不清楚我需要第一个构造函数,因为它只有std::function
的2个参数。
修改
作为Lol4t0注释,它适用于另一个编译器。看来VS.NET问题。 Example 1,Example 2
我正在使用Microsoft Visual Studio 2013.任何人都可以重现吗?
答案 0 :(得分:2)
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”,这会削弱这种元编程。