删除移动构造函数的模糊重载

时间:2012-12-04 12:43:14

标签: c++ g++

如果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

while clang 3.2 RC2和VC11(如果我用Test(T&&) = delete;替换private: Test(T&&);)接受代码。

我看不出哪里应该含糊不清。

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

2 个答案:

答案 0 :(得分:5)

已删除的构造函数参与重载解析(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<int> &const Test<double> &的第一个(唯一)参数中的参数类型;可用的转换序列是:

  1. int左值; int &; Test<int>临时的; const Test<int> &
  2. int左值; int右值; double右值; double &&; Test<double>临时的; const Test<double> &
  3. 这两个序列是等级的用户定义的转换序列,因此是不明确的。删除构造函数Test<double>::Test(double &&)的事实在此阶段无关紧要。

答案 1 :(得分:1)

海湾合作委员会有一个开放的错误:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425

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