The problem is that std::unique_ptr has its own copy constructor marked as =delete . This means that calling vec.push_back(elem) inside add(T const&) overloaded member function will not compile when called with std::unique_ptr . The compiler will understand this as soon as this member function is created.
The standard contains 2 relevant quotes here in 14.7.1 Implicit Instance [temp.inst] :
6 If the overload resolution process can determine the correct function to call without an instance of the definition of the class template, it is unclear whether this is a creation.
10 [...] It is not clear whether the implementation implicitly creates an instance of the virtual member function of the class template, unless the virtual member function is otherwise created. [...]
Section 6 states that without the virtual compiler is allowed but not required to instantiate both add(T const&) and add(T&&) to decide which overload is best. Neither gcc 4.7.2 nor Clang 3.2 require instantiation because they infer that rvalue links are always better for temporary than lvalue links.
Section 10 states that - even with the virtual - the compiler is also allowed, but not required to instantiate add(T const&) and add(T&&) to decide which overload is best. Both gcc 4.7.2 and Clang 3.2 occur with instances of both member functions, although both of them could infer that lvalue overloading would never be a better match.
Please note: if you make ContainerWrapper regular class with a nested typedef unique_ptr<string> T; then gcc and Clang will generate errors with or without the virtual keyword, because they must generate code for both member functions. This will not be excluded from SFINAE because an error does not occur when substituting the output arguments.
Conclusion : this is not a mistake , but a problem .
TemplateRex
source share