mam zagadkę który próbuję rozwiązać, i zasadniczo sprowadza się do następującego przykładu:CRTP i rodzaj widoczność
template <typename CT>
struct A
{
typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
};
template <typename CT>
struct B
{
typedef typename CT::BAR BAR;
BAR foo() {}
};
template <typename DT>
struct C : B<C<DT> >
{
typedef DT VALUE_T;
typedef typename A<C>::FOO BAR;
};
int main() {
C<int> c;
}
mogę spróbować wyjaśnić powyższe (próbowałem około trzy razy i usunięty tekst), ale w zasadzie wymagania są:
C
musi dziedziczyć zB
wpisane zC
(wydobywająca CRTP), tjB<C<>>
C
jest jedynym, który może utworzyć wystąpienieA
(tj.A
musi być wpisany zC
)A
jest jedynym, który może określićFOO
(FOO
jest zależna od rodzajuCT
, związek jest bardziej skomplikowana niż przedstawiony)
Problem (jak można patrz powyższy kod) jest to, że typ BAR
jest dostępny tylko w zakresie C
i jest niekompletny, gdy B
jest utworzony, dlatego B
nie widzi typu BAR
z argumentem szablonu CT
(C<int>
). Niestety w zakresie B
, typ BAR
jest używany jako argumenty funkcji i typy zwracane (to znaczy nie tylko ograniczone do zakresu funkcji - w rezultacie nie mogę po prostu przenieść zakresu typedef do funkcji).
Czy istnieje sposób obejścia tego? Nie mogę złamać wyżej wymienionych związków (chyba że w ostateczności). Przypuszczalnie przy pomocy C++ 11, mógłbym użyć auto
i obejść potrzebę posiadania BAR
typedef w B
, jednak obecnie nie jest to jeszcze opcja.
EDYCJA: podążanie za komentarzem @bitmasks, trochę więcej informacji.
- Kod w
A
iB
służy się w kilku plików binarnych w różnych sytuacjach, tylko wyjątkowa sytuacja w tym przypadku jest to, żeC
wywodziB
, w pozostałych przypadkachC
posiada instancję czegoś pochodzącego zB
. - Argumenty szablonu można zmienić (w
A
iB
), o ile mogą być domyślnie ustawione na wartości, które nie wymagają zmiany istniejących zastosowańA
iB
. Ten sam zestaw typów musi być dostępny jako domyślny parametr szablonu lub inny mechanizm.
Używam szablonów po prostu dlatego, że wymagam ścisłego sprzężenia i potrzebuję elastyczności, aby użyć kodu w różnych sytuacjach.
Opisy elementów:
A
najlepiej można opisać jako kontener iFOO
naprawdę jest iterator, co zawiera określony jest przez typedef parametru szablonuB
najlepiej można opisać jako klasa podstawowa, która zawiera zestaw funkcji, które są wywoływane przez niektóre komponenty posiadane przez instancjęC
. W poprzednich przypadkach składniki te zostały przekazane jako odniesienie do rzeczy pochodzących zB
(i te rzeczy są również własnościąC
), w tym przypadku, zapewniam odwołanie do samejC
.
Głównym powikłaniem wynika z dostępu do pojemnika A
wcześniej związek między B
i C
że C
ma instancję z B
, ale teraz C
jest instancją z B
- ta zmiana semantyki przerw sposób w jaki typy są wstrzykiwane do klas.
Od dłuższego czasu myślałem o twoim dylemacie i myślę, że musisz podać więcej informacji, dlaczego robisz objazd przez te wszystkie aliasy i jakie zmiany w twoim przykładzie są dopuszczalne (np. Dodatkowe parametry, dodatkowe typy itp.). – bitmask
@bitmask, dziękuję za poświęcony mi czas, dodałem więcej informacji, oprócz prawdziwego kodu (którego nie mogę opublikować, ponieważ jest bardzo wrażliwy), próbuję opisać sytuację w aktualizacji. Sedno problemu polega na tym, że typy muszą być dostępne, niezależnie od tego, czy relacja między 'C' i' B' jest * ma * lub * jest a *. – Nim
@Nim: Bardzo mylące i ładnie odczytywane przez bitmask. Czy możesz powiedzieć, dlaczego jesteś w takiej sytuacji? – Arunmu