Eksperymentuję z nowymi funkcjami C++ 11. W mojej konfiguracji bardzo chciałbym używać dziedziczących konstruktorów, ale niestety żaden kompilator ich jeszcze nie implementuje. Dlatego próbuję zasymulować to samo zachowanie. Mogę napisać coś takiego:wykrywanie chronionych konstruktorów (prawdopodobnie abstrakcyjnych) klasy bazowej
template <class T>
class Wrapper : public T {
public:
template <typename... As>
Wrapper(As && ... as) : T { std::forward<As>(as)... } { }
// ... nice additions to T ...
};
To działa ... przez większość czasu. Czasami kod używający klasy Wrapper
musi wykorzystywać SFINAE, aby wykryć, jak można skonstruować taki model Wrapper<T>
. Jest jednak następujący problem: jeśli chodzi o rozdzielczość przeciążania, konstruktor Wrapper<T>
zaakceptuje dowolne argumenty - ale wtedy kompilacja nie powiedzie się (i jest to nie objęte SFINAE), jeśli typ T
nie może zostać skonstruowany z wykorzystaniem tych.
starałem się warunkowo włączyć różne dawałaby szablonu konstruktora używając enable_if
template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
Wrapper(As && ... as) // ...
który działa dobrze tak długo, jak:
- odpowiedni konstruktor
T
jestpublic
T
nie jest abstrakcyjna
Moje pytanie brzmi: jak pozbyć się powyższych dwóch ograniczeń?
że próbuje przezwyciężyć najpierw sprawdzenie (stosując SFINAE i sizeof()
) czy ekspresja new T(std::declval<As &&>()...)
dobrze uformowanej ciąguWrapper<T>
. Ale to oczywiście nie działa, ponieważ jedynym sposobem, w jaki klasa pochodna może korzystać z chronionego konstruktora bazy, jest lista inicjalizacji członka.
Po drugie, nie mam pojęcia - i jest to ten, którego potrzebuję więcej, ponieważ czasami jest to Wrapper
, który implementuje abstrakcyjne funkcje T
, co czyni go kompletnym typem.
że chce roztwór którym:...
- jest prawidłowy standardowych
- prace lub gcc-4,6 * gcc-4,7 * lub szczęk-3 *
Dzięki!
Jestem w pośpiechu, ale może http://stackoverflow.com/questions/8984013/can-sfinae-detect-private-access-violations może pomóc tutaj, nie liczyłbym na gcc 4.6 dostając to prawy chociaż – PlasmaHH
Kontrola dostępu jest tu nieco trudna: jeśli użyjesz 'sizeof()', kompilator sprawdzi całe wyrażenie, dostęp zostanie włączony - ale potem zostanie sprawdzony dostęp ** z kontekstu wyrażenia **, co nie powiedzie się w przypadku chronionych konstruktorów; wszystko inne niż 'sizeof' działa tylko na poziomie rozdzielczości przeciążenia i typu wnioskowania, więc naruszenia dostępu nie wywołają SFINAE - ale wtedy nie widzę możliwości zrobienia czegoś z konstruktorem, ponieważ nie można go przekazać jako argumentu szablonu . Jeśli chodzi o obsługę kompilatora, będę szczęśliwy, jeśli ** dowolny ** z powyższych akceptuje kod. –