2013-04-25 6 views
5

Jest to raczej pytanie o standard C++. Rozważmy następujący kod:Prywatny test istnienia członka za pomocą meta-programowania, GCC vs clang, co jest zgodne z prawdą?

template <typename T> 
class has_Data 
{ 
    typedef char one; 
    typedef long two; 

    template <typename C> static one test(typeof(&C::Data)) ; 
    template <typename C> static two test(...); 

public: 
    enum { value = sizeof(test<T>(0)) == sizeof(char) }; 
}; 

class MyClass { 
private: 
    struct Data { 
    }; 
}; 


void function(bool val = has_Data<MyClass>::value) {} 

Powyższy kod działa z gcc (GCC) 4.4.3

Jednak przy clang version 3.3 (2545b1d99942080bac4a74cda92c620123d0d6e9) (2ff97832e593926ea8dbdd5fc5bcf367475638a9)

daje ten błąd:

test_private_data.cpp:7:54: error: 'Data' is a private member of 'MyClass' 
    template <typename C> static one test(typeof(&C::Data)) ; 
                ^
/devshared/home/rhanda/test_private_data.cpp:7:37: note: while substituting explicitly-specified template arguments into function template 'test' 
    template <typename C> static one test(typeof(&C::Data)) ; 
            ^
/devshared/home/rhanda/test_private_data.cpp:21:26: note: in instantiation of template class 'has_Data<MyClass>' requested here 
void function(bool val = has_Data<MyClass>::value) {} 
         ^
1 error generated. 

Który z nich ma rację?

Ze standardowego dokumentu (n3485) znalazłem oświadczenie, które wydaje się zgadzać z językiem większym niż gcc.

Access control is applied uniformly to all names, whether the names are referred to from declarations or expressions.

+0

Co to jest typeof? – ForEveR

+0

Czy chodziło Ci o jeden statyczny test (nazwa_klasy :: Dane *); Jestem tylko ciekawy, co 'decltype (& C :: Data)' robi dla ciebie ... – lapk

+0

To samo .. po prostu wykrywanie, czy funkcja może być rozwiązana w pierwszej, czy nie. Jeśli zrobię zmianę w użyciu Twój kod ... robi to samo, jak przypuszczam. – RamneekHanda

Odpowiedz

3

Zakładam, że GCC ma rację.

Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że żaden kod inny niż friend powinien być w stanie pozytywnie zgłosić istnienie danego członka prywatnego. Więc jeśli to właśnie próbujesz zrobić, musisz zmodyfikować swój projekt. Klasa może robić wszystko z prywatnymi członkami, a inny kod (z wyjątkiem przyjaciół) nie powinien mieć możliwości dowiedzenia się o tym. To według projektu. Jest to zasada . Ponieważ MyClass::Data jest prywatne, kod w has_Data powinien - moim zdaniem - zachowywać się tak, jakby w ogóle nie było członka C::Data. Stąd pierwsza funkcja prowadziłaby do niepowodzenia substytucji, która zostaje cicho zignorowana, a druga funkcja jest używana. Dodając nieco więcej kodu, mój GCC 4.7.2 kompiluje to bez problemów i z has_Data<MyClass>::value z oceną na false. Poprawnie SFINAE w mojej opinii.

Próbując kopię tej opinii z cytatem z the document you referred to, znalazłem następujące w punkcie 14.8.2 pkt 8:

Note: Access checking is done as part of the substitution process.

To jest nienormatywne uwaga w normie, ale mi się wydaje być bardzo czytelnym i wyraźnym wskazaniem, że SFINAE powinna faktycznie stosować się w tej sytuacji, dokładnie tak, jak GCC ją obsługuje.

Edytuj: Jako @hvd wskazano w a comment, powyższe odnosi się tylko do C++ 11. W starszych wersjach standardu sytuacja była inna. Issue 1170: Access checking during template argument deduction zawiera szczegóły dotyczące tej zmiany.

GCC nie skompiluje tego kodu z -std=c++03 lub -std=c++11 z powodu faktu, że typeof jest rozszerzeniem GNU. Fakt, że -std=gnu++03 nadal kompiluje kod, może być może uważany za niewłaściwy, ale ponieważ droga naprzód wykorzystuje semantykę C++ 11, nie zawracałbym sobie głowy raportowaniem o tym.

+1

IIRC, czyli jedna z nowych funkcji C++ 11, a przed C++ 11, sprawdzanie dostępu miało nastąpić później. Pytanie nie określa, czy kod został skompilowany w trybie C++ 11. – hvd

+0

@hvd: Dobra uwaga! Na podstawie [tej odpowiedzi] (http://stackoverflow.com/a/8984268/1468366) dowiedziałem się o [Wydanie 1170: Sprawdzanie dostępu podczas dedukcji argumentu szablonu] (http://wg21.cmeerw.net/cwg/issue1170) tam, gdzie ta zmiana była dyskutowana i podjęta decyzja. – MvG

Powiązane problemy