явная специализация члена - PullRequest
4 голосов
/ 16 декабря 2010

g ++ 3.4.5 принимает этот код:

template <typename T> struct A
{
    static const char* const str;
};

struct B {};

typedef A<B> C;

template<> const char* const C::str = "B";
// Equivalent to following?
// template<> const char* const A<B>::str = "B";

Но я не уверен, что это на самом деле законно C ++ 03. В частности,

[14.7p3] В явном объявлении специализации для шаблона класса, члена шаблона класса или шаблона члена класса, имя класса, который явно специализирован, должно быть идентификатором шаблона.

Говорит ли это требование, что в конце этого примера должна использоваться версия без определения типа? Или я что-то неверно истолковал?

Редактировать: Дополнительные доказательства: Отчет о дефектах 403 предполагает, что неверно говорить, что тип (в этом контексте тип аргумента выражения вызова функции) является template-id потому что template-id имеет синтаксическое, а не семантическое значение. В последующих проектах стандарта использовалась «специализация шаблона класса» вместо « template-id » в 3.4.2.

Это поддерживает аргумент, что хотя A<B> и C представляют один и тот же тип (и имеют идентичное или почти идентичное семантическое значение), A<B> представляет собой идентификатор шаблона и C нет, потому что термин template-id относится к синтаксическому содержимому как к последовательности токенов, а не к значению этих токенов.

Ответы [ 2 ]

4 голосов
/ 16 декабря 2010

Я думаю, что это строго неправильно (по крайней мере, в соответствии с C ++ '03).

Моя логика заключается в том, что хотя typedef (7.1.3 / 1):

... таким образом, является синонимом для другого типа.

В стандарте все еще есть слова, которые явно разрешают использовать typedef, когда требуется class-name (7.1.3 / 4):

typedef-name, которое называет класс, является class-name

Нет таких слов для template-id.

0 голосов
/ 16 декабря 2010

Полагаю, здесь нет явной специализации. Вы можете написать подобный код без шаблонов:

struct A
{
    static const char* const str;
};

typedef A C;

const char* const C::str = "B";

Этот код является абсолютно правильным, даже если вы используете C вместо A. C - просто псевдоним.

Только представьте, как обрабатывается код C ++. Очевидно, что typedefs расширяются компилятором еще до запуска процесса создания шаблона. Так же, как все комментарии раскрываются перед макросами. Поскольку все макросы раскрываются препроцессором еще до начала фактического разбора C ++. Это все упрощает.

Что касается стандарта C ++ 03, взгляните на это

7.1.3 / 1 Имя, объявленное с помощью спецификатора typedef, становится ЬурейеЕ имя. В рамках его объявление, typedef-имя синтаксически эквивалентно ключевому слову и называет тип, связанный с идентификатор в порядке, описанном в пункт 8. Таким образом, typedef-name является синоним другого типа. typedef-name не вводит новый введите способ объявления класса (9.1) или enum объявление делает.

Полагаю, этот абзац ясно объясняет, что C в вашем коде на самом деле является идентификатором шаблона.

...