本文介绍了保护CRTP模式免于“纯虚拟"网络中的堆栈溢出.来电的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下标准CRTP示例:

Consider the following standard CRTP example:

#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 方法标记为像

If this was regular virtual inheritance I could have mark virtual f and g methods as pure like

struct Base {
    virtual void f() = 0;
    virtual void g() = 0;
};

并得到有关 Foo 为抽象的编译时错误.但是CRTP没有提供这种保护.我可以以某种方式实施它吗?运行时检查也是可以接受的.我曾考虑过将 this-> f 指针与 static_cast< Derived *>(this)-> f 进行比较,但未能使其正常工作./p>

and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.

推荐答案

这里是另一种可能性:

#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之前使用'auto Base :: g()[with Derived = Foo]'),而对于Clang,它给出了 Base< Foo> :: g 的无限递归模板实例的可读性稍差的示例,而 g 实例化了自身,但最终以错误结束.

For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.

这篇关于保护CRTP模式免于“纯虚拟"网络中的堆栈溢出.来电的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 14:17