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?
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.
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.
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...
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