Why is_copy_constructible static assertion on a template argument fails?

c++, c++11, copy-constructor

Solution

Q1 Why is compile-time check false and "run-time" true? Does it fail because the class (Fun) is not fully instantiated/defined at the check time?

Yes. `FunContainer<Fun>` is instantiated before `Fun` is defined, when you use it as `Fun`'s base class.

Q2 Is this expected?

Yes.

Q3 Is there a way to make a compile-time assertion that would check if class is CopyConstructible with similar design?

Move your static assertion somewhere that gets instantiated at a later time. Inside `FunContainer`'s constructor seems like a good choice to me.

Problem

I tried to make a static assertion on a template parameter, to check/enforce the `Type` to be copy constructible. However the static assertion fails. I fail to understand why, and cannot find any documentation why would it fail on static evaluation. The instantiated class is copy constructible, however it uses what I believe is called curiously recurring template parameter pattern. Below is the whole test code: ``` #include <iostream> #include <type_traits> using namespace std; template<typename Type> class FunContainer { // static_assert(is_copy_constructible<Type>::value, "Type must be copy constructible!"); // <- This fails. // bool copyable = is_copy_constructible<Type>::value // <- will make the second assert fail protected: int container_stuff = 0; public: int get_container_stuff() {return container_stuff;}; void set_container_stuff(int stuff) {container_stuff = stuff;}; bool is_copyable() {return is_copy_constructible<Type>::value;}; }; class Fun : public FunContainer<Fun> { public: std::string str = "Tastic"; Fun() = default; Fun(const Fun& other_fun) : FunContainer<Fun>(other_fun) { copy_internals(other_fun); }; Fun& operator=(const Fun& other_fun){ FunContainer<Fun>::operator=(other_fun); copy_internals(other_fun); return *this; }; private: void copy_internals(const Fun& other_fun) {str = other_fun.str;}; }; static_assert(is_copy_constructible<Fun>::value, "Type must be copy constructible!"); // <- the 2nd assert int main() { Fun fun; fun.set_container_stuff(10); fun.str = "test"; Fun tastic(fun); cout << tastic.get_container_stuff() << '\n'; cout << tastic.str << '\n'; cout << tastic.is_copyable() << '\n'; return 0; } ``` Result is as expected: ``` 10 test 1 ``` Which means the 2nd assert passed. So it seems that the `Fun` is not CopyConstructible inside the `FunContainer`. However, the `is_copyable` says it is. I also tried to change `is_copyable()` method to use a `bool` initialized in-class It makes the second assertion fail. When obstructing assertions are removed the value is of `copyable` gets set to 0; It seems that only evaluation failing is static copmile-time within the base class. Q1 Why is compile-time check `false` and "run-time" `true`? Does it fail because the class (`Fun`) is not fully instantiated/defined at the check time? Q2 Is this expected? (That the static evaluation of is_copy_constructible gives result than different "run-time" one). Q3 Is there a way to make a compile-time assertion that would check if class is CopyConstructible with such a design? Tested on clang 3.2-11, gcc 4.8.2 and ideone default c++11 compiler.

Original source