考虑以下标准CRTP示例:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
如果这是常规的虚拟继承,则可以将虚拟
f
和g
方法标记为纯净的struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
并获得有关
Foo
为抽象的编译时错误。但是CRTP没有提供这种保护。我可以以某种方式实现它吗?运行时检查也是可以接受的。我曾考虑过将this->f
指针与static_cast<Derived *>(this)->f
进行比较,但未能使其正常工作。 最佳答案
这是另一种可能性:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
对于GCC,它给出了非常清楚的错误消息(“错误:在扣除“自动”之前使用'auto Base::g()[with Derived = Foo]'”),而对于Clang,它给出的可读性稍差无限递归
Base<Foo>::g
的模板实例化,g
实例化自己,但最终以错误结束。关于c++ - 防止CRTP模式在 “pure virtual”调用中堆栈溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45163209/