【问题标题】:ambiguous overload with deleted move constructor带有删除的移动构造函数的模棱两可的重载
【发布时间】:2012-12-04 12:43:14
【问题描述】:

如果 BREAK,g++ 4.6.3 和 4.7.2 无法编译以下代码(在 c++0x 模式下) 已定义。

template<class T> struct Test {
    Test(T&) {}
#ifdef BREAK
    Test(T&&) = delete;
#endif
};

void func(Test<int> const&) {}
void func(Test<double> const&) {}

int main()
{
    int x = 0;
    func(x);
    return 0;
}

错误是

error: call of overloaded 'func(int&)' is ambiguous

虽然 clang 3.2 RC2 和 VC11(如果我将 Test(T&amp;&amp;) = delete; 替换为 private: Test(T&amp;&amp;);)接受代码。

我看不出哪里有歧义。

这是一个 g++ 问题吗? (不知道在gcc的bug列表中搜索什么...)

【问题讨论】:

  • FWIW,= deleted 函数不会从重载决议中删除。这仅意味着如果重载决议选择了它们,则程序是不正确的。
  • 是的,但它是 func,这是模棱两可的。原始代码中的Teststd::reference_wrapperdeleted 构造函数是为了防止引用临时对象,IIUC。

标签: c++ g++


【解决方案1】:

已删除的构造函数参与重载决议(Are the special member functions always declared?);这是必要的,以便可以使用已删除的构造函数来防止转换(摘自 8.4.3p3):

struct onlydouble {
  onlydouble(std::intmax_t) = delete;
  onlydouble(double);
};

在编译过程中执行函数删除很晚,在重载决议(8.4.3p2)之后,因此重载决议无法根据删除区分构造函数。 gcc 正确,clang 和 VC11 错误。

请注意,在函数调用表达式 func(x) 中存在歧义,其中参数 x 是类型为 int 的左值,而 id func 表示在第一个(仅)中具有参数类型的重载集const Test&lt;int&gt; &amp;const Test&lt;double&gt; &amp;的参数;那么可用的转换序列是:

  1. int左值; int &amp;; Test&lt;int&gt;临时; const Test&lt;int&gt; &amp;,
  2. int左值; int右值; double右值; double &amp;&amp;; Test&lt;double&gt;临时; const Test&lt;double&gt; &amp;

这两个序列是用户定义的等阶转换序列,因此是不明确的。构造函数Test&lt;double&gt;::Test(double &amp;&amp;)被删除的事实在这个阶段是无关紧要的。

【讨论】:

  • 嗯...我看不出这在哪里相关。我正在调用func,并带有对int 的左值引用(g++ 告诉我)。现在Test&lt;int&gt; 可以从int&amp; 隐式构造,而Test&lt;double&gt; 不是。所以唯一可行的重载是func(Test&lt;int&gt; const&amp;),不是吗?
  • @Alex Test&lt;double&gt; 可以通过算术转换从 int 隐式构造为 double,然后是右值引用绑定。
  • 我以为我明白你的答案,所以我提交了bug report。不过好像还不是很清楚……
  • @Alex 我已经用我的推理更新了那个错误报告; DR 1164 不适用,因为即使在没有模板的情况下也会出现此错误。
【解决方案2】:

GCC 中有一个开放的错误:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425

CLANG 是正确的,GCC 需要解决这个问题。

【讨论】:

  • 我不认为这是同一个问题...在错误报告中,第一个 fT = int 匹配,第二个 fT = int&amp; 匹配,因此打电话给f是模棱两可的。但是在上面的问题中没有涉及到模板参数推导。
  • 有缺陷报告,应该没有歧义 --open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164
  • 你可能是对的...我已经提交了bug report。也许你想看看?
  • 好的,谢谢。我对 Kaelyn Uhrain 所说的话没有任何补充。 CLANG 有正确的行为。 Daniel Krügler(gcc 开发人员)确认这是 GCC 中的一个错误。
猜你喜欢
  • 2017-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
相关资源
最近更新 更多