由于 std::function,构造函数重载中的歧义
Ambiguity in constructor overload because of std::function
我想对某些 class 的构造函数进行两次重载,如下所示:
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。任何人都可以复制吗?
MSVC 2013 std::function
只是一个 C++11 std::function
,没有来自(如果我没记错的话)缺陷报告的附加功能。
此附加功能是 template<class F> function(F&&)
构造函数类似于 SFINAE,仅限于类型 F
,因此 function
实际上可以从该类型构造。 (该标准不强制要求基于 SFINAE 的实现)
实际上,std::function
有一个 "try constructing from anything" 构造函数。当它失败时,它对于重载解析来说失败得太晚了。至少在 MSVC2013 中。所以你的两个 std::function
看起来都是有效的重载。
我相信 2015 的最新版本 std::function
具有 有限的 能力来完成您请求的过载。
在 2013 年,您可以做一个可能有效的解决方法,但这很痛苦。
首先,了解如何重载函数对象集。然后,创建一个函数对象 F
和另一个采用 Tpoint, Tpoint
和 returns some_special_tag_type
的函数对象的重载集。现在,将 Tpoint, Tpoint
传递给该重载集,并跟踪 return 类型是否为 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 或不依赖重载可能更容易。
请注意,如果您重载 return 类型而不是参数类型,则此技术实际上是可行的。这很难,因为即使 MSVC2015 也没有 "expression SFINAE",这削弱了这种元编程。
我想对某些 class 的构造函数进行两次重载,如下所示:
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
.
编辑:
作为Lol4t0评论,它适用于另一个编译器。看来是VS.NET的问题。 Example 1 , Example 2
我正在使用 Microsoft Visual Studio 2013。任何人都可以复制吗?
MSVC 2013 std::function
只是一个 C++11 std::function
,没有来自(如果我没记错的话)缺陷报告的附加功能。
此附加功能是 template<class F> function(F&&)
构造函数类似于 SFINAE,仅限于类型 F
,因此 function
实际上可以从该类型构造。 (该标准不强制要求基于 SFINAE 的实现)
实际上,std::function
有一个 "try constructing from anything" 构造函数。当它失败时,它对于重载解析来说失败得太晚了。至少在 MSVC2013 中。所以你的两个 std::function
看起来都是有效的重载。
我相信 2015 的最新版本 std::function
具有 有限的 能力来完成您请求的过载。
在 2013 年,您可以做一个可能有效的解决方法,但这很痛苦。
首先,了解如何重载函数对象集。然后,创建一个函数对象 F
和另一个采用 Tpoint, Tpoint
和 returns some_special_tag_type
的函数对象的重载集。现在,将 Tpoint, Tpoint
传递给该重载集,并跟踪 return 类型是否为 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 或不依赖重载可能更容易。
请注意,如果您重载 return 类型而不是参数类型,则此技术实际上是可行的。这很难,因为即使 MSVC2015 也没有 "expression SFINAE",这削弱了这种元编程。