c++ - 仅在使用时如何在成员函数中进行静态断言?

标签 c++ inheritance static-assert

我有以下方案:

struct Baz {};
struct Qux {};

struct Base {
  virtual ~Base() {}
  virtual void foo() = 0;
};

template<typename T> struct Identity { static bool const value = false; };
template<typename T> void bar(T) { static_assert(Identity<T>::value, "Busted!!!"); }
template<> void bar<Baz>(Baz) {}

template<typename T>
struct Derived : Base {
  T m;
  void foo() { bar(m); }
};

int main() {
  Base *b0 = new Derived<Baz>;
  b0->foo();
  Base *b1 = new Derived<Qux>;
  (void) b1;
}

也就是我有一个纯虚类Base和一个模板类 Derived继承自 Base并覆盖纯虚函数 foo按要求。现在,里面 foo我调用函数模板 bar . bar具有类 Baz 的特化但不适用于类(class) Qux .当在 main我正在尝试实现 Derived<Baz> 的对象一切都好。但是当我尝试实现 Derived<Qux> 的对象时编译器命中 static_assert .

问:

有没有一种方法可以转换我的代码,使编译器在 Derived<Qux> 中命中静态断言?仅当Derived<Qux>::foo()被称为。

即物化Derived<Qux>的一个对象将通过:

Base *b1 = new Derived<Qux>;

但是当程序员稍后在代码中尝试调用时:

b1->foo(); // compile error static assert

最佳答案

该标准在 [temp.inst]/9 中说明了一件有趣的事情:

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement, unless such instantiation is required. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.

实例化虚函数的决定取决于实现,但前提是在其他情况下不需要。因此,我们面临的问题是:什么时候需要根据标准本身进行定义?

答案在[class.virtual]/11[temp.inst]/2 :

A virtual function declared in a class shall be defined, or declared pure in that class, or both; no diagnostic is required

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions

因此类模板的任何实例化都会实例化Derived::foo 的声明,这通过链式 react 需要一个定义。因此定义也必须实例化,如果可用的话。

实现可以行使它在第一个引用段落中给出的回旋余地的唯一方法是如果 Derived::foo 也是纯虚拟的。例如,ClangGCC就那样做。当然,这可能对您的帮助有限。

所以长话短说,只要函数是虚拟的(而不是纯虚拟的),它就不会启动。

关于c++ - 仅在使用时如何在成员函数中进行静态断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46341681/

相关文章:

c++ - 使用 lodePng 和 OpenGL 显示 png 图像

c++ - consteval 会允许在函数参数上使用 static_assert 吗?

c++ - static_assert 在宏中,但也扩展为可以用作函数参数的东西

c++ - 如何从 C++ 中的 curl 输出中搜索所有出现的正则表达式?

c++ - 将派生指针隐式转换为其相应基址的引用

c++ - 从 C++ 编写 .csv 文件

c++ - 虚继承中的重载虚函数

c++ - 强制调用 "highest"重载函数而不是基函数

class - 使用其他方法创建 Ocaml 子类的正确方法是什么?

c++ - static_assert 可以检查类型是否为 vector 吗?