考虑以下标准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
}

如果这是常规的虚拟继承,则可以将虚拟fg方法标记为纯净的
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/

10-11 16:32