If it were called std::has_copy_constructor, there would be no need to write even the title of this article, let alone the body.
Also, maybe this should require a diagnostic due to it being statically obvious that it is calling a deleted constructor:
Derived(Derived const& d) : Base<T>(d) {}
... and if we use regular non-template classes, it does!Clang:
#include <type_traits>
struct Base
{
// Default-constructible
Base() = default;
// Not copy-constructible
Base(Base const &) = delete;
};
struct Derived : Base
{
Derived() = default;
Derived(Derived const& d) : Base(d) { }
};
Clang: copy-constructor.cc:15:33: error: call to deleted constructor of 'Base'
15 | Derived(Derived const& d) : Base(d) { }
| ^ ~
copy-constructor.cc:9:5: note: 'Base' has been explicitly marked deleted here
9 | Base(Base const &) = delete;
| ^
1 error generated.
If the program requires a diagnostic which allows it to be rejected entirely, it then doesn't matter what is_copy_constructible returned.The only reason we don't get a diagnostic is that the language plays it loose with templates, in many cases deferring type checks until instantiation.
It is possible to argue that is_copy_constructible isn't necessarily badly named, but rather foiled by templates.