繁体   English   中英

如何将函数断言为 CRTP 的最终函数?

[英]How to assert a function as final for CRTP?

正如我们在 CRTP 中所知道的,派生类继承基类,作为最终继承。

如果我们想让派生类不是 final 但“覆盖”函数是“final”怎么办?

有没有办法用static_assert来实现?

代码示例:

template <typename D>
struct A
{
    int f()
    {
        return static_cast<D*>(this)->g();
    }

    int g();
};

struct B : A<B> // usually final, but we want it inheritable
{
    int g() // but this should be 'final'
    {
        // TODO: ???
        return 1;
    }
};

struct C : B
{
    int g() // this is bad
    {
        return 2;
    }

    int h(); // this is permissive
};

#include <iostream>

template <typename D>
void f(A<D>& x)
{
    std::cout << x.f() << std::endl;
}

int main()
{
    B b;
    C c;
    f(b); // OK, it's 1
    f(c); // BAD, it's 1
    return 0;
}

您可以将final用于两个目的。

来自https://en.cppreference.com/w/cpp/language/final

指定不能在派生类中覆盖虚函数或不能继承类。

您可以使用

struct B : A<B>
{
    virtual int g() final
    {
        return 1;
    }
};

允许其他类从B派生但不能覆盖g()

使用final另一个潜在好处是优化编译器可能能够在编译时解析函数调用,而不是在运行时解析(感谢 @JesperJuhl)。

我想出了一个在函数签名中使用私有标签的解决方案:

template <typename D>
struct A
{
    struct internal_tag
    {};

    int f()
    {
        return static_cast<D*>(this)->g({});
    }

    int g(internal_tag);
};

struct B : A<B>
{
    int g(internal_tag)
    {
        return 1;
    }

private:
    using A<B>::internal_tag;
};

struct C : B
{
    //  int g(internal_tag) // int g(internal_tag) is prohibited
    //  {
    //      return 2;
    //  }

    int h();
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM