为什么模板参数上的is_copy_constructible静态断言失败?

时间:2014-02-18 13:35:42

标签: c++ c++11 copy-constructor

我尝试在模板参数上进行静态断言,以检查/强制Type是可复制构造的。但静态断言失败了。我无法理解为什么,也找不到任何文档,为什么它会在静态评估中失败。

实例化的类是可复制构造的,但是它使用我认为被称为奇怪的重复模板参数模式。

以下是整个测试代码:

#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;
}

结果符合预期:

10
test
1

这意味着第二个断言通过了。所以似乎Fun不是FunContainer内的CopyConstructible。但是,is_copyable表示确实如此。

我还尝试将is_copyable()方法更改为使用bool初始化的类中它使第二个断言失败。当阻止断言被删除时,copyable的值被设置为0;

似乎只有评估失败才是基类中的静态copmile-time。

Q1 为什么编译时检查false和“运行时”true?是否因为在检查时没有完全实例化/定义类(Fun)而失败?

Q2 这是预期的吗? (is_copy_constructible的静态评估给出的结果不同于“运行时”)。

Q3 有没有办法制作一个编译时断言来检查类是否是具有这种设计的CopyConstructible?

在clang 3.2-11,gcc 4.8.2和ideone default c ++ 11编译器上测试过。

1 个答案:

答案 0 :(得分:6)

  

Q1 为什么编译时检查错误,“运行时”为真?是否因为在检查时没有完全实例化/定义类(Fun)而失败?

是。 FunContainer<Fun>Fun定义之前被实例化,当您将其用作Fun的基类时。

  

Q2 这是预期的吗?

  

Q3 有没有办法进行编译时断言,检查类是否具有类似设计的CopyConstructible?

将静态断言移动到稍后实例化的某个位置。内部FunContainer的构造函数对我来说似乎是一个不错的选择。