11

g++ 4.6.3 and 4.7.2 fail to compile the following code (in c++0x mode) if BREAK is defined.

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;
}

The error is

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

while clang 3.2 RC2 and VC11 (if I replace Test(T&&) = delete; with private: Test(T&&);) accept the code.

I can't see where that should be ambiguous.

Is this a g++ issue? (I don't know what to search for in the gcc bug list...)

Alex
  • 709
  • 3
  • 10
  • 6
    FWIW, `= delete`d functions are not removed from overload resolution. It only means that if overload resolution picks them, the program is ill-formed. – R. Martinho Fernandes Dec 04 '12 at 12:56
  • 1
    Yes, but it's `func` which is ambiguous. `Test` in the original code is a `std::reference_wrapper` and the `delete`d constructor is to prevent reference to temporaries, IIUC. – Alex Dec 04 '12 at 13:22

2 Answers2

7

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.

Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Hm... I don't see where this is relevant here. I am calling `func` with an lvalue-reference to an `int` (g++ tells me). Now `Test` is implicitly constructible from an `int&`, while `Test` is not. So the only viable overload is `func(Test const&)`, isn't it? – Alex Dec 04 '12 at 13:33
  • @Alex `Test` is implicitly constructible from an `int` via arithmetic conversion to `double` and then rvalue reference binding. – ecatmur Dec 04 '12 at 13:39
  • I thought I understood your answer, so I have submitted a [bug report](http://llvm.org/bugs/show_bug.cgi?id=14505). But it seems it's not that clear... – Alex Dec 05 '12 at 19:45
  • @Alex I've updated that bug report with my reasoning; DR 1164 doesn't apply because this bug obtains even in the absence of templates. – ecatmur Dec 10 '12 at 16:01
1

There is open bug in GCC: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425.

CLANG is correct, GCC needs to fix this.

Leonid Volnitsky
  • 8,854
  • 5
  • 38
  • 53
  • I don't think this is the same problem... In the bug report, the first `f` matches with `T = int` and the second `f` matches with `T = int&` and therefore the call to `f`is ambiguous. But in the problem above no template argument deduction is involved. – Alex Dec 05 '12 at 09:42
  • There is defect report, it should not be ambigues -- http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1164 – Leonid Volnitsky Dec 05 '12 at 13:06
  • You might be right... I have submitted a [bug report](http://llvm.org/bugs/show_bug.cgi?id=14505). Maybe you want to have a look? – Alex Dec 05 '12 at 19:49
  • Yes, thanks. I don't have anything add to what Kaelyn Uhrain said. CLANG have correct behavior. Daniel Krügler (gcc developer) confirmed that this is a bug in GCC. – Leonid Volnitsky Dec 05 '12 at 20:17