disclaimer: nie mam okazji wlaczyc kompilatora g++ ani nawet msvc zeyb sprawdzic to co napisalem i zaraz napisze, stad jest to obecny moj domysl
disclaimer2: pomijam public/private/protected - oczywiste
nie widze powodu dlaczego kompilator, KTORY ZAUWAZYL ze Inner2 jest pochodna Inner, niemialy zauwazac ze Inner2 zawiera pole liczba. Przeciez to zwykle dziedziczenie! jesli jest w stanie znalezc klase Inner, to zna jej pola skladowe, wiec nie powinien miec problemu.
zuooo napisał(a)
A bez niczego kompilator po prostu szuka symbolu w przestrzeni bez klasy Base (i przez to Inner)
jesli tak jest, to w przypadku:
class X
{
class Y { int blah; }
class Z : Y { Z() { blah = 5; } }
}
klasa Z tez by ni ewidziala pola blah --- nigdy tego zachowania nie zauwazylem...
moim zdaniem, problem tkwi w tym, ze Base jest szablonem i zapis Inner2 : Inner jest niejednoznaczny. sadze ze kompilator NIE WIDZI klasy Inner tak jak powinien.
"Inner" jest faktycznie "Base<T>::Inner" i nie jest wiadome czy chodzi o to samo <T> w 'zakresie' ktorego jest deklarowane Inner2 czy o inne -- calkowicie legalne przeciez byloby:
A<double>::C cos; gdzie:
template <T> class A{
class B{ T x; }
class C : A<int>::B {}; // dla B T:=int a nie double!
class C : B {}; // A<..?..> ::B
}
stad, domyslam sie, ze w ramach poprawki wystarczy:
template<T> class Base{
class Inner {}
class Inner2 : Base<T>::Inner {}
}
przyczym, mozliwe przeciez jest takze:
template <T> class A{
class B{ T x; }
class C : B {};
}
template <> class A<int> { //specjalizacja szablonu klasy A dla int'a - nie posiadajaca B ani C
class X {}
}
</cpp>
wiec wyraznie B i C sa symbolami zaleznymi, ktore dopiero w konkretyzacji szablonu sie ujawnia albo okaza nieistniejace!
stad moj pomysl na naprawienie brzmi:
template<T> class Base{
class Inner {}
class Inner2 : typename Base<T>::Inner {}
}
co przyznam, nie wiem czy jest w 100% skladniowo poprawne, ale tak ja bym to widzial.
edit: zostawiam zamieszczony tok myslenia, ale -- szukajac dalej, natrafilem na: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18 co dokladnie opisuje ten przypadek.
to co podal zuoooo jest wlasciwe. problem rzeczywiscie, tak jak sadzilem, tkwi w dependent/nondependent names, ale nie Inner/Inner2 jak sadzilem -- tylko faktycznie w samym "liczba".
cytujac mozliwe poprawki, wystarczy zamienic symbol "liczba" na jedno z :
- taka jak podal uuuu: ---------- this->liczba
- taka jak podal zuooo: ---------- using Base<T>::liczba
- taka jak podalem, ale gdzie indziej :) ---------- Base<T>::liczba