Propagacja "typedef" z klasy bazowej na pochodną dla "szablonu"

Próbuję zdefiniować klasę bazową, która zawiera tylko typedef.

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
private:
    Vec_t v;  // fails - Vec_t is not recognized
};

Dlaczego w B dostaję błąd, że Vec_t nie jest rozpoznawany i muszę go wyraźnie napisać?

typename A<T>::Vec_t v;
Author: curiousguy, 2009-10-29

7 answers

Uważam, że to pytanie jest zduplikowane, ale nie mogę go teraz znaleźć. Standard C++ mówi, że należy w pełni zakwalifikować nazwę zgodnie z 14.6.2/3:

W definicji szablonu klasy lub elementu szablonu klasy, jeśli klasa bazowa szablonu klasy zależy od parametru szablonu, zakres klasy bazowej nie jest sprawdzany podczas wyszukiwania bez zastrzeżeń nazwy ani w punkcie definicji szablonu klasy lub elementu, ani podczas tworzenia instancji klasy szablon lub członek.

UPD: I found duplicate finally: here it is.

 45
Author: Kirill V. Lyadvinsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:57

Istnieje coś, co nazywa się zależnymi i nie zależnymi nazwami w przypadku szablonów.

Jeśli nazwa zależy od parametru szablonu t to zależne nazwa i inne, które nie zależą od parametru T są niezależne nazwy.

Oto zasada: kompilator nie szukać w zależnych klasach bazowych (jak A) patrząc w górę nazwy (np. Vec_t). W rezultacie, kompilator nie wie, że nawet istnieć nie mówiąc już o tym, że są typy.

Kompilator nie może zakładać, że Vec_t jest typem, dopóki nie zna T, ponieważ istnieje potencjalna specjalizacja A<T> Gdzie A<T>:: Vec_t jest członkiem danych

Więc rozwiązaniem jest użycie typename

 typename A<T>::Vec_t v;  ← good

Polecam Ci przejść przez to https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types .

Stary (uszkodzony) link: http://www.parashift.com/c++ - faq-lite / templates.html#faq-35.18

 42
Author: Xinus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 13:53:56

Ponieważ kompilator nie jest pewien, że Vec_t nazywa Typ. Na przykład, A<T> może być wyspecjalizowane dla T=int do , a nie mieć ten konkretny typedef.

 8
Author: Jesse Beder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-29 11:38:38

Dla kompletności, oto jak możesz złagodzić ten uciążliwość trochę, albo:

  • przepisać te typy w klasach pochodnych, lub lepiej - jak z metody -
  • po prostu zaimportuj te nazwy w klasie pochodnej z using declaration:

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

private:
    Vec_t v;
};

Może być przydatne, jeśli masz więcej niż jedną wzmiankę o dziedziczonej typedef w klasie pochodnej. Nie musisz też dodawać typename za każdym razem z tym.

 6
Author: Roman Kruglov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-06 16:34:50

Musisz jednoznacznie zakwalifikować użycie Vec_t, ponieważ kompilator nie wie, skąd pochodzi Vec_t.

Nie może zakładać niczego o strukturze A, ponieważ szablon klasy A może być wyspecjalizowany. Specjalizacja może zawierać Vec_t, który nie jest typedef, lub może nawet nie zawierać członka Vec_t w ogóle.

 2
Author: user200783,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-29 11:40:21

Vec_t nie jest nazwą zależną, a kompilator musi wiedzieć co to jest bez tworzenia instancji szablonów (w tym przypadku klasa bazowa). Naprawdę nie różni się od:

template <class T>
class X
{
    std::string s;
}

Tutaj również kompilator musi wiedzieć o std:: string, nawet jeśli X nie jest instancją, ponieważ nazwa nie zależy od argumentu szablonu T (O ile kompilator może zakładać).

Podsumowując, typedefs w klasie bazowej szablonu wydają się raczej bezużyteczne do użycia w klasie pochodnej. Do rodzaju należą następujące gatunki przydatne jednak dla użytkownika.

 1
Author: UncleBens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-29 11:44:13

Pojęcie to może być związane ze sposobem, w jaki używamy std::vector<T>. Na przykład, jeśli mamy std::vector<int> Foo. Teraz zdecydujemy się użyć dowolnego z jego typów, powiedzmy iterator. W tym scenariuszu wyraźnie wspominamy

std::vector<int>::iterator foo_iterator;

Podobnie w Twoim przypadku, aby użyć typu public member Vec_t z template <typename T> class A, musisz jawnie zadeklarować go jako

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
 1
Author: RAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 17:01:59