【问题标题】:Ambiguity in constructor overload because of std::function由于 std::function 导致构造函数重载的歧义
【发布时间】:2016-02-12 23:34:19
【问题描述】:

我想对某个类的构造函数进行两次重载,如下所示:

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。任何人都可以复制吗?

【问题讨论】:

  • 我认为这两者都不适用,因为它不会返回 int
  • 对不起,我在简化时忘记编辑它
  • 我觉得还可以ideone.com/qDeZKr
  • @Lol4t0:是的!我在另一个在线编译器上尝试过,它成功了!这似乎是一个 vs.net 错误?

标签: c++ c++11 visual-studio-2013 std-function compiler-bug


【解决方案1】:

MSVC 2013 std::function 只是 C++11 std::function,没有(如果我没记错的话)缺陷报告中的附加功能。

此附加功能是 template&lt;class F&gt; function(F&amp;&amp;) 构造函数类似于 SFINAE,仅限于仅适用于类型 F 以便 function 实际上可以从该类型构造。 (该标准不强制要求基于 SFINAE 的实施)

实际上,std::function 有一个“尝试从任何东西构造”构造函数。而当它失败时,它对于重载解决方案的失败为时已晚。至少在 MSVC2013 中。所以你的两个std::functions 看起来都是有效的重载。

我相信 2015 年最新版本的 std::function 具有有限能力来完成您要求的重载。

在 2013 年,您可以做一个可能有效的解决方法,但它是一个痛苦。

首先,学习如何重载函数对象集。然后,创建一个函数对象F 和另一个接受Tpoint, Tpoint 并返回some_special_tag_type 的函数对象的重载集。现在,将Tpoint, Tpoint 传递给该重载集,并跟踪返回类型是否为some_special_tag_type。将此决定从foo(int, F&amp;&amp;) 重载标记为foo_impl(tag_1, int, std::function&lt;blah_1&gt;)foo_impl(tag_2, int, std::function&lt;blah_2&gt;)

升级到 MSVC2015 可能更容易,或者不要依赖重载。

请注意,如果您重载返回类型而不是参数类型,则此技术实际上是可行的。这很难,因为即使是 MSVC2015 也没有“表达式 SFINAE”,这会削弱这种元编程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多