101*_*010 11 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;
}
Run Code Online (Sandbox Code Playgroud)
也就是说,我有一个纯虚拟类Base和一个模板类Derived,它根据需要继承Base和覆盖纯虚函数foo.现在,foo我在里面调用函数模板bar.bar有专门的课程,Baz但没有课Qux.在main我试图实现Derived<Baz>一切物体的确定时.但是当我尝试实现Derived<Qux>编译器命中对象时static_assert.
有没有办法以这样一种方式转换我的代码,即编译器Derived<Qux>只有在Derived<Qux>::foo()被调用时才会命中静态断言.
也就是说,实现一个对象Derived<Qux>将通过:
Base *b1 = new Derived<Qux>;
Run Code Online (Sandbox Code Playgroud)
但是当程序员稍后在代码中尝试调用时:
b1->foo(); // compile error static assert
Run Code Online (Sandbox Code Playgroud)
Sto*_*ica 10
标准在[temp.inst]/9上说了一个有趣的事情:
实现不应隐式实例化函数模板,变量模板,成员模板,非虚拟成员函数,成员类,类模板的静态数据成员或constexpr if语句的子语句,除非这样的实例化是必须的.如果虚拟成员函数不会被实例化,则实现是否隐式实例化类模板的虚拟成员函数是未指定的.
实例化虚拟功能的决定取决于实现,但只有在不需要的情况下才能实现.因此,我们面临的问题是:根据标准本身何时需要定义?
答案是[class.virtual]/11和[temp.inst]/2:
在类中声明的虚函数应该在该类中定义或声明为纯,或者两者都是; 无需诊断
类模板特化的隐式实例化会导致声明的隐式实例化,而不会导致类成员函数的定义,默认参数或noexcept-specifiers的实例化.
因此,类模板的任何实例化都将实例化一个声明Derived::foo,通过连锁反应需要一个定义.因此,如果可用,定义也必须实例化.
实现可以在第一个引用段落中给出的余地的唯一方法是,如果它Derived::foo也是纯虚拟的.举个例子,Clang和GCC都是这样做的.那当然可能对你的帮助有限.
所以长话短说,只要功能是虚拟的(而不是纯虚拟的),它就是一个不起作用的东西.
| 归档时间: |
|
| 查看次数: |
1028 次 |
| 最近记录: |