I am currently reading a book (C++ Templates: The Complete Guide 2e) that explains that a member function template will never replace the special member functions like a copy constructor, and if you define only a copy-constructor as a template, then the compiler still generates one for you.
However, the author also included a terse hack that overrides this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class C
{
public:
...
// user-define the predefined copy constructor as deleted
// (with conversion to volatile to enable better matches)
C(C constvolatile&) = delete;
// implement copy constructor template with better match:
template<typename T>
C (T const&) {
std::cout << "tmpl copy constructor\n";
}
...
};
This seems interesting. However my question is why the argument is marked volatile. I understand the concept of this, but I don't see why converting to volatile enables "better matches." Could someone elucidate?
If it doesn't have "volatile" then it won't match a volatile object. By having both const and volatile it will match any cv-qualified or non-qualified object.
What exactly would be the purpose of a volatile object? I get what volatile does, it prevents the compiler from making certain optimizations in a loop like this:
1 2
volatileint a = 40;
while(a == 40) {...}
I get the concept for basic types like int. But what does making a class object volatile do?
I don't see why converting to volatile enables "better matches"
Perhaps the meaning is: to be sure to match any possible parameter passed (it could be a āCā declared const volatile), do delete the copy constructor which accepts a const volatile reference.
(Just an hypothesis)
This implicitly-declared copy constructor has the form T::T(const T&) if ā¦ [omissis]
Otherwise, the implicitly-declared copy constructor is T::T(T&). (Note that due to these rules, the implicitly-declared copy constructor cannot bind to a volatile lvalue argument.)