Подтвердить что ты не робот

Как определить, является ли класс окончательным в С++ 11?

Сначала код.

#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?

4b9b3361

Ответ 1

Типовые черты обычно реализуются с использованием идиомы SFINAE, которая помещает потенциально неправильно сформированное выражение внутри объявления шаблона функции. Подстановка соответствующего имени в декларацию приводит к ошибке, но в этом контексте ошибка подавляется, поэтому декларация либо используется, либо нет. Но резервная перегрузка поддерживает потенциально отсутствующую декларацию. Еще один бит кода обращается к функции, чтобы определить, была ли реализована чувствительная перегрузка или только резервная копия.

Это не будет работать для final, потому что это может привести к сбою при создании экземпляра шаблона. Там нет способа перегрузить классы, и нет возможности предварительно определить класс, который будет терпеть неудачу, но не остановить компиляцию в случае, если он был получен из окончательного.

Стандартная цитата, С++ 11 §14.8.2/8:

Только недопустимые типы и выражения в непосредственном контексте типа функции и ее типа параметров шаблона могут привести к ошибке дедукции. [Примечание. Оценка замещенных типов и выражений может приводить к возникновению побочных эффектов, таких как создание специализированных специализированных шаблонов классов и/или функциональных шаблонов, генерация неявно определенных функций и т.д. Такие побочные эффекты не находятся в "непосредственном контекста" и может привести к плохому формированию программы. - конечная нота]

Ответ 2

Как разработчик GCC __is_final intrinisic (для PR 51365) Я уверен, что это невозможно сделать в библиотеке, ему нужна поддержка компилятора.

Вы можете сделать некоторые очень умные вещи с помощью функции CIN 11 SFINAE для выражений, но для определения того, является ли класс окончательным, что вам нужно извлечь из него, и создать экземпляр производного типа в контексте вывода аргумента шаблона, но вывод из класса выполняется в декларации, а не в выражении.

Кроме того, вы должны подумать, хотите ли вы только знать, было ли использовано псевдослово final или если класс не выводим по другим причинам, например, только с частными конструкторами.

Ответ 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;
}