10

g++ 4.6.3 および 4.7.2 は、BREAK が定義されている場合、(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&&) = delete;た場合private: Test(T&&);) はコードを受け入れます。

どこがあいまいなのかわかりません。

これは g++ の問題ですか? (gcc バグ リストで何を検索すればよいかわかりません...)

4

2 に答える 2

6

Deleted constructors participate in overload resolution (Are the special member functions always declared?); this is necessary so that one can use deleted constructors to prevent conversions (excerpted from 8.4.3p3):

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

Enforcement of function deletion comes very late in the compilation process, after overload resolution (8.4.3p2) and so overload resolution cannot distinguish between constructors on the basis of deletion. gcc is correct and clang and VC11 are incorrect.

Note that the ambiguity is in the function call expression func(x), where the argument x is an lvalue of type int and the id func denotes an overload set with parameter types in the first (only) parameter of const Test<int> & and const Test<double> &; the available conversion sequences then are:

  1. int lvalue; int &; Test<int> temporary; const Test<int> &,
  2. int lvalue; int rvalue; double rvalue; double &&; Test<double> temporary; const Test<double> &.

The two sequences are user-defined conversion sequences of equal rank, and so are ambiguous. The fact that the constructor Test<double>::Test(double &&) is deleted is irrelevant at this stage.

于 2012-12-04T13:22:39.227 に答える
1

GCCには未解決のバグがあります:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425

CLANGは正しいです。GCCはこれを修正する必要があります。

于 2012-12-04T14:43:20.797 に答える