Użycie słowa kluczowego typename z parametrami funkcji szablonu

W C++, słowo kluczowe typename jest potrzebne, aby kompilator mógł rozróżnić zagnieżdżone typy i zagnieżdżone wartości w szablonach. Istnieją jednak pewne sytuacje, w których nie jest możliwa dwuznaczność, na przykład gdy klasa pochodna dziedziczy po zagnieżdżonym typie klasy.

template <class T>
class Derived : public T::type
{ };

Tutaj słowo kluczowe typename nie jest wymagane, a w rzeczywistości nawet nie jest dozwolone. Ma to sens, ponieważ kontekst usuwa niejednoznaczność. Tutaj, T::type musi odnosić się do typu, ponieważ oczywiście nie można dziedziczyć z wartość.

Myślę, że to samo dotyczy parametrów szablonu funkcji.

template <class T>
void foo(const T::type& v)
{

}

W tym przypadku kontekst wyjaśnia, że {[4] } musi odnosić się do typu, ponieważ parametr funkcji nie może być wartością. Jednak kompilator tego nie akceptuje. Chce const typename T::type&. To wydaje się niespójne. Dlaczego język pozwala na domyślne założenie typu zagnieżdżonego w kontekście dziedziczenia, ale Nie w kontekście parametrów funkcji? W obu przypadkach tam nie może być dwuznaczności, więc dlaczego potrzeba typename w jednym, a nie w drugim?

Author: Channel72, 2010-12-03

3 answers

Jeśli lekko zmienisz swoją deklarację, otrzymasz zupełnie inną historię

template <class T>
void foo(T::type& v);
To już nie jest jednoznaczne. Może zadeklarować zmienną typu void, która jest inicjalizowana przez bitowe wyrażenie AND. Cała deklaracja byłaby wzorowana. Oczywiście, to wszystko semantycznie jest nonsensem, ale składniowo jest w porządku.

Wygląd pojedynczego const składniowo sprawia, że jest on jednoznaczny, ale zbyt duża zależność kontekstu, aby to działało w kompilator. Musi pamiętać, że odczytuje const lub jakąkolwiek inną tego typu rzecz, a kiedy parsuje T::type po tym, będzie musiał pamiętać, aby przyjąć tę nazwę jako typ. Dodatkowo wydmuchiwałoby to i tak już skomplikowany Standard nie do wiary.

Zmieńmy jeszcze raz deklarację funkcji

template <class T>
void foo(const T::type);

Nawet pojawienie się const tam nie zapewnia jednoznacznego parsowania. Czy powinna to być deklaracja funkcji z nienazwanym parametrem, czy też deklaracja funkcji z nieprawidłową nazwą parametru, która nie ma swojego typu? Nazwa parametru jest przetwarzana przez declarator-id, która może być również nazwą kwalifikowaną. Tak więc, const będzie należeć do specyfikacji typu, podczas gdy T::type będzie parsowany przez kompilator jako nazwa parametru, w przypadku braku typename. To też jest całkowicie nonsensowne, ale jest poprawne składniowo.

W przypadku nazw klas bazowych samo name lookup stwierdza, że nazwy innych typów są ignorowane. Więc dostajesz pominięcie typename za darmo: nazwa, którą name lookup daje większej liczbie modułów wyższego poziomu kompilatora, albo odnosi się do typu, albo name lookup poda błąd.

Napisałem wpis FAQ o Gdzie umieścić "szablon" i "typename" na nazwach zależnych.

 22
Author: Johannes Schaub - litb,
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 11:53:31

Po pierwsze, nie sądzę, aby kiedykolwiek było intencją, aby dokonać ostrego i precyzyjnego rozróżnienia między sytuacjami, w których dozwolone są tylko nazwy typów (jak nazwa klasy bazowej), a sytuacjami, w których dozwolone są również encje nie-typowe (jak wyrażenia). Powiedziałbym, że kontekst nazwy klasy bazowej został wyodrębniony z jakiegoś innego powodu.

Po drugie, nie jest do końca poprawne stwierdzenie, że w deklaracjach parametrów funkcji każdy encja jest koniecznie nazwą typową. Parametr Można zadeklarować jako follows

template <class T>
void foo(const T::type& v[T::value]);

Oczywiście gramatyka w tym przypadku wyraźnie nakazuje, że {[1] } musi być nazwą typową, a value musi być wartością. Jednak kompilator może tylko dowiedzieć się, że po analiza składniowa deklaracji, podczas gdy uważam, że idea typename została wprowadzona, aby pomóc kompilatorowi w faktycznie rozpoczynając właściwą analizę składniową kodu, tzn. rozróżnienie powinno być dostępne przed analiza składniowa, jako wkład do analizy składniowej. analiza składniowa. Rozróżnienie to może mieć głęboki wpływ na interpretację Kodeksu.

 4
Author: AnT,
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
2010-12-03 17:34:39

Byłoby interesujące dowiedzieć się, co jest przyczyną tego.

Próbowałem przeczytać standard w poszukiwaniu odpowiedzi, proszę zauważyć, że jestem nowicjuszem w tym.

Jednak uważam, że znalazłem odpowiednią klauzulę.

§14.6.2. Nazwa używana w szablonie deklaracja lub definicja i to jest zależny od parametru szablonu jest przyjmuje się, że nie należy nazywać typu , chyba że odnośne wyszukiwanie nazw wyszukuje Typ nazwa lub nazwa jest kwalifikowana przez słowo kluczowe typename .

Sugeruje to, że problem polega na tym, jak działa name lookup dla bazowych list specyfikacji i argumentów funkcji.

Base specifier name lookup:

§10.2. Podczas wyszukiwania bazy nazwa klasy, nazwy nie-typów są ignorowane (3.3.10).

Co wyjaśnia, dlaczego typename nie jest wymagane dla specyfikacji bazowych.

Nadal szukam nazwy argumentu funkcji.

Proszę popraw mnie, jeśli jest to błędne lub nieistotne założenie. W międzyczasie wciąż kopię.

Błąd podany przez VS2010, gdy nie kwalifikuje argumentu szablonu w deklaracji funkcji jest następujący:

'T::type': dependent name is not a type prefix with 'typename' to Wskaż typ.

Jednak nadal Nie wiem, co do zasad wyszukiwania nazw zależnych argumentów funkcji...

 2
Author: ronag,
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
2010-12-03 17:19:53