Note; gcc and clang show the correct behavior when trying to compile the provided fragment.
Why is vc++ incorrectly accepting a fragment?
A function template can never be created in such a way as to create an instance constructor, which can be read in the following two citations from the C ++ standard:
[ class.copy ]
2) A constructor without a template for class X is a copy constructor if its first parameter is of type X& , const X& , volatile X& or const volatile X& , and either there are no other parameters, otherwise all other parameters have default arguments (8.3.6) .
...
6) The constructor declaration for class X poorly formed if its first parameter is of type (optionally cv-qualified) X , and either there are no other parameters or all other parameters have default arguments. A member function template is never created to create such a signature -constructor.
If the move constructor is explicitly declared, the implicitly created instance constructor will not be callable, see the following:
[ class.copy ]
7) If the class definition does not explicitly declare the copy constructor, one is declared implicitly. If the class definition declares a move constructor or transfers an assignment operator, the implicitly declared copy constructor is defined as deleted ; otherwise, it is defined as default (8.4)
struct Obj { template<typename T> Obj (T const&) { } Obj (Obj&&) { } }; ... Obj a; Obj b (a);
With the previously mentioned quotes from the C ++ standard, we can easily see that the above definition of Obj would be semantically equivalent below, since our explicitly declared constructor move would make our implicitly declared instance constructor = delete; .
struct Obj { template<typename T> Obj (T const&) { } Obj (Obj const&) = delete; Obj (Obj&&) { } };
In accordance with the rules for overload resolution, remote functions are still involved in the search for the best match, but if they win the battle for what works best, the program is poorly formed. This is exactly what happens in the fragment.
Obj (Obj const&) = delete better than template<typename T> Obj (T const&) , but since the copy constructor cannot be called, the fragment will not compile.
source share