2015-10-07 22 views
5

Próbuję publicznie wyprowadzić klasę z szablonu, który sprawi, że dziedziczy ona po klasie bazowej i uzyskuje dostęp do chronionych członków. Ale zanim to rozbudowany szablon nie ma tych praw, a więc nie można użyć elementu bazowego jako parametr szablonu:Dostęp do klasy bazowej szablonu przed rozwinięciem szablonu uzyskanego z

using Fun = void (*)(); 

class Base { 
protected: 
    // friend class Derived; // ...need this to eliminate complaint 
    static void something(); 
}; 

template<Fun F> 
class Variant : public Base {}; 

class Derived : public Variant<&Base::something> { // `something()` is protected 
public: 
    void somethingElse() { 
     something(); // doesn't complain about this `something()` 
    } 
}; 

int main() {} 

Dziwne trochę o to, aby mnie było to, że Friending to działało w ogóle. Zastanawiałem się, czy mogę „podkradają Pochodzące w drzwiach”, umieszczając publiczne wirtualnego dziedziczenie z bazy przed Variant:

class Derived : public virtual Base, public Variant<&Base::something> 

To nie pomogło.

Pytanie: jest jakiś inny trik na uniknięcie wyraźnej wzmianki o wszystkich klasach pochodnych w Bazie, ale nadal mieć dostęp do zabierania chronionych członków z niego dla parametrów szablonu?

(Uwaga:.. Próbując to na starszej GCC 4.6.3, wygląda nawet Friending nie pomoże w tym przypadku wydaje się więc, że obsługa jest dość nowy)

+3

Powiązane: [CWG 372] (http://wg21.cmeerw.net/cwg/issue372) i [CWG 580] (http://wg21.cmeerw.net/cwg/issue580). Wydaje się, że nawet obecne wersje clang ++ i g ++ nie implementują proponowanej rozdzielczości dla tej drugiej wady. – dyp

+0

@dyp Myślę, że to prawdopodobnie "odpowiedź" lub tak blisko, jak to tylko możliwe. Chcesz to zrobić? – HostileFork

Odpowiedz

1

Przyklej obrażanie dostępu do metafunkcji. Wyprowadź klasę metafunkcji z bazy.

template<typename B> 
struct something_variant : public B { 
    typedef Variant< & B::something > type; 
}; 

class Derived : public something_variant<Base>::type { 
    … 

http://coliru.stacked-crooked.com/a/6bca00455bd3daca

chodzi KGR 372 krytyczna artykułu rozdzielczości jest to,

[A] Kontrola ccess Base-specyfikatorami musi być odłożona do całego bazowego specifier- lista została zauważona.

Zostało to już zaakceptowane w C++ 11, więc interesujące jest to, że Twój przykład został odrzucony. I, plugging odpowiedni przykładowy kod ze standardu C++ 11 do ostatnich Clang i GCC pokazuje, że po prostu nie wdrożyły odroczenia. Jest to co najmniej trochę zaskakujące, ponieważ implementacja wymaga struktury danych reprezentującej zestaw odroczonego sprawdzania dostępu ... dość dużego wysiłku dla przypadku narożnego.