[英]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.