我有以下方案:
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
也是纯虚拟的。例如,Clang和 GCC就那样做。当然,这可能对您的帮助有限。
所以长话短说,只要函数是虚拟的(而不是纯虚拟的),它就不会启动。
关于c++ - 仅在使用时如何在成员函数中进行静态断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46341681/