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...)
noexcept is nice for two reasons: The compiler can optimize a little better because it doesn't need to emit any code for unwinding a call stack in case of an exception, and. It leads to incredible performance differences at runtime for std::vector (and other containers, too)
If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then: No move constructor is automatically generated. No move-assignment operator is automatically generated.
Move constructor moves the resources in the heap, i.e., unlike copy constructors which copy the data of the existing object and assigning it to the new object move constructor just makes the pointer of the declared object to point to the data of temporary object and nulls out the pointer of the temporary objects.
A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.
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:
int
lvalue; int &
; Test<int>
temporary; const Test<int> &
,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.
There is open bug in GCC: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425.
CLANG is correct, GCC needs to fix this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With