23

先上代码。

#include <iostream>

using namespace std;

struct A final {};
struct B {};

int main()
{ 
    cout << is_final<A>::value << endl; // Output true
    cout << is_final<B>::value << endl; // Output false

    return 0; 
}

如何实现类is_final?

4

3 回答 3

30

作为 GCC 的__is_finalintrinisic(对于PR 51365)的实现者,我很确定它不能在库中完成,它需要编译器支持。

您可以使用 C++11 的 SFINAE 表达式功能做一些非常聪明的事情,但是要检测一个类是否是最终的,您需要从它派生,并在模板参数推导上下文中实例化派生类型,但是从一个类是在声明而不是表达式中完成的。

此外,您应该考虑是否只想知道是否使用了final伪关键字,或者是否由于其他原因(例如只有私有构造函数)无法派生类。

于 2012-12-10T22:23:28.310 回答
12

类型特征通常使用 SFINAE 习惯用法来实现,它将一个可能不正确的表达式放在函数模板声明中。将有问题的类型名替换到声明中会导致错误,但在该上下文中会抑制错误,因此要么使用声明,要么不使用声明。但是后备重载支持可能丢失的声明。另一段代码访问该函数以检测是否实例化了敏感过载或仅实例化了备份。

这不起作用,final因为它只会在类的模板实例化期间导致失败。没有办法重载类,也没有办法暂时定义一个会失败但不会停止编译的类,以防它派生自 final。

标准报价,C++11 §14.8.2/8:

只有在函数类型及其模板参数类型的直接上下文中的无效类型和表达式会导致推导失败。[注意:替换类型和表达式的评估可能会导致副作用,例如类模板特化和/或函数模板特化的实例化,隐式定义函数的生成等。此类副作用不在“立即上下文”,并可能导致程序格式错误。——尾注]

于 2012-12-10T22:32:47.733 回答
-3

不确定这是否是您想要的,但您可以执行以下操作:

#include <iostream>

struct Foo {};
struct Bar {};

template<typename T>
struct is_final {
    static const bool value = false;
};
template<>
struct is_final<Bar> {
    static const bool value = true;
};


int main(void) {
    std::cout << is_final<Foo>::value << std::endl;
    std::cout << is_final<Bar>::value << std::endl;
}
于 2012-12-10T22:09:00.297 回答