2012-12-10 12 views
17

Kod pierwszy.Jak wykryć, czy dana klasa jest ostateczna w C++ 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; 
} 

Jak wdrożyć klasę is_final?

+2

Dziki domysł: to niemożliwe. system typu C++ nie utrzymuje dającego się przejść łącza do podklas danej klasy, tylko odwrotnie (przez łańcuch dziedziczenia). Co właściwie chcesz osiągnąć? (Wciąż +1, interesujące, zwięźle zadawane pytanie.) –

+1

Nie jestem pewien, czy można wyzwolić warunek SFINAE, który pozwoliłby ci to przetestować. Wiem, że G ++ implementuje słowo kluczowe __is_final, które to robi, ale to wszystko, co znalazłem. Jest to zależne od implementacji, ale może być ograniczone w przypadku. –

+0

Myślę, że to również niemożliwe bez wsparcia kompilatora. Może warto [propozycja na przyszły standard] (http://isocpp.org/forums/iso-c-standard-future-proposals), aby dodać 'std :: is_final'. – Xeo

Odpowiedz

8

Cechy charakterystyczne są zwykle implementowane za pomocą idiomu SFINAE, który umieszcza potencjalnie niezdefiniowane wyrażenie wewnątrz deklaracji szablonu funkcji. Zastąpienie nazwy pliku w deklaracji powoduje błąd, ale w tym kontekście błąd jest pomijany, więc deklaracja jest albo używana, albo nie. Ale przeciążenie awaryjne wspiera potencjalnie brakującą deklarację. Kolejny bit kodu uzyskuje dostęp do funkcji wykrywania, czy wystąpiło wrażliwe przeciążenie, czy tylko kopia zapasowa.

To nie zadziała dla final, ponieważ może tylko spowodować awarię podczas tworzenia instancji szablonu. Nie ma możliwości przeciążenia klas i nie ma możliwości wstępnego zdefiniowania klasy, która zawiedzie, ale nie zatrzyma kompilacji na wypadek, gdyby pochodziła z wersji ostatecznej.

Standardowy cytat, C++ 11 §14.8.2/8:

Tylko nieprawidłowe typy i wyrażeń w bezpośrednim kontekście rodzaju funkcji i jej typów parametrów szablonu może spowodować awarii odliczenia. [Uwaga: Ocena podstawionych typów i wyrażeń może skutkować efektami ubocznymi, takimi jak tworzenie specjalizacji szablonów klas i/lub specjalizacjami szablonów funkcji, generowanie niejawnie zdefiniowanych funkcji itd. Takie efekty uboczne nie występują w "bezpośrednim" kontekście "i może spowodować, że program będzie źle sformułowany. - nota końcowa]

0

Nie wiem, czy to jest to, co chcesz, ale można zrobić coś takiego:

#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; 
} 
+7

Myślę, że źle zrozumiałeś pytanie. –

+0

Rozumiem, że nie możesz tego zrobić bez sprecyzowania, czy klasa jest ostateczna, czy nie. – gvd

+2

@gvd 'final' to (nowe, kontekstowo warunkowe) słowo kluczowe, które można zastosować do deklaracji klasy. Chce wykryć, czy został użyty. – Potatoswatter

23

jako realizator GCC __is_final intrinisic (dla PR 51365) Jestem pewien, że nie można zrobić w bibliotece potrzebuje obsługi kompilatora.

Możesz zrobić kilka bardzo sprytnych rzeczy za pomocą funkcji SFINAE C++ 11 dla wyrażeń, ale aby wykryć, czy klasa jest ostateczna, z której musisz czerpać, i utworzyć instancję typu pochodnego w kontekście odjęcia od szablonu, ale wywodzące się z klasy odbywa się w deklaracji, a nie wyrażenia.

Powinieneś również pomyśleć, czy chcesz się dowiedzieć, czy użyto pseudo-słowa kluczowego final, czy też klasa nie może być uzyskana z innych powodów, na przykład z prywatnych konstruktorów.

+1

Jeśli kiedykolwiek zostanie to uwzględnione w standardzie, może być potrzebna dwie propozycje - 'is_final' i' is_derivable', obie implementujące inną semantykę. Chociaż w TMP posiadanie prywatnych konstruktorów nie przeszkadza w wyprowadzaniu, ponieważ zazwyczaj nie konstruuje się takich typów. – Xeo

+0

@Xeo 'is_derivable' byłoby mylące dla testu dostępnych konstruktorów, ponieważ nadal możesz wywodzić i używać klasy bez żadnych niestatycznych członków bez konstruktora. – Potatoswatter

+0

... uh, chciałem powiedzieć, że możesz używać statycznych członków. – Potatoswatter

Powiązane problemy