Question

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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top