Здравствуйте Sergey, Вы писали:
S>Это template type parameter класса foo, а не тип.
Ага... Так бы и формулировал с самого начала, а не в партизанов игрался В таком ракурсе давай сначала и по порядку:
S>>>Как это может быть явной специализацией, если тип Т не задан?
ПК>>Специализацией это является, потому что присутствует `template<>'.
S>Это не довод. Наличие template<> с тем же успехом может говорить, например, о синтаксической ошибке. В данном случае оно, IMHO, говорит только о том, что автор кода хотел, чтобы это было специализацией.
Это уже философский вопрос, чего хотел автор. Для компилятора важно, что получилось. Синтаксически `template < > declaration' (14.7.3), [2] является явной специализацией. О семантике (времени компиляции в т.ч.) программ, содержащих диагностируемые ошибки рассуждать бессмысленно. Например, следуя предложенной тобой логике, в частности, можно сформулировать, например, такие (в той же степени истинные) утверждения:
1) foo не является шаблоном класса, т.к. тело шаблона содержит ошибку;
2) f не является шаблоном члена шаблона класса, т.к. foo не является шаблоном класса (т.к. 1);
3) template<> void f(const T &val) не является специализацией шаблона класса, т.к. содержит как минимум две ошибки: подобная специализация не разрешена в теле шаблона класса и без явной специализации включающего шаблона класса
и т.д.
ПК>>>>14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
S>>>Ну и где здесь "can be deduced from the function argument type"?
<...> S>>>Типа аргумента-то нет, в отличие от примера в процитированном пункте стандарта.
ПК>>Тип аргумента T.
S>Это template type parameter класса foo, а не тип.
Шаблон класса порождает множество несвязанных классов, в каждом из которых template type parameter привязан к соответствующему template type argument, который является каким-то типом. Поэтому я и написал аргумента T. Например:
template<class T>
class C
{
T t;
};
Следуя твоей логике можно было бы задать вопрос: "какого типа переменная t?". Да никакого, до тех пор, пока шаблон C не будет конкретизирован и template type parameter не будет привязан к какому-либо template type argument. Точно так же и в приведенном примере шаблона foo T обозначает какой-то тип. Выяснять какой бессмысленно до тех пор, пока шаблон foo не конкретизирован и template type parameter не привязан к template type argument. Когда это произошло, T обозначает тип соответствующего template type argument.
До тех же пор стандартом требуется, чтобы члены шаблона не порождались и, соответственно, подавляются всякие семантические проверки типа "provided it can be deduced from the function argument type", кроме тех, которые будут приводить к ошибкам при любых аргументах шаблона. Например, аналогично есть требование о том, что тип переменной должен быть законченным, или что два перегруженных метода класса должны иметь разные сигнатуры (т.е. разные соглашения о вызовах и/или типы аргументов и/или константность и т.п.). Однако эти правила в общем случае не могут быть проверены для членов шаблона класса:
template<class T>
class C
{
void f(int);
void f(T);
T t;
};
поэтому проверка этих правил откладывается до конкретизации шаблона, а компилятор ограничивается проверкой синтаксиса.
В примере шаблона foo с синтаксисом все в порядке. Поэтому, если бы не явные запреты, то исходный пример был бы верен, т.к. явная специализация функции-члена f порождалась бы, как и другие члены шаблона только при ее использовании. Я не вижу причин, почему компилятор не смог бы вывести необходимую информацию без `<T>' аналогично другим подобным случаям.
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) { ... } // [1]template<>
void f(const T &val) { ...} // [2]
};
[2] будет являться полной или же частичной специализацией [1]? Можно ли вообще специализировать прямо в классе или нужно выносить отдельно?
Спасибо заранее.
Здравствуйте Sergey, Вы писали:
O>>[2] будет являться полной или же частичной специализацией [1]? Можно ли вообще специализировать прямо в классе или нужно выносить отдельно?
S>Полной. Только перед T вроде typename писать полагается.
Если можно, обоснование. Я тоже думаю, что полной, но вот хотелось бы быть 100% уверенным.
O>[2] будет являться полной или же частичной специализацией [1]?
Согласно текущей версии стандарта это является ошибкой, т.к. шаблон члена шаблона класса не может быть специализирован без специализации шаблона содержащего класса (14.7.3/18).
O>Можно ли вообще специализировать прямо в классе или нужно выносить отдельно?
Шаблоны членов класса должны специализироваться вне тела класса (14.7.3/2).
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте orangy, Вы писали:
O>>>[2] будет являться полной или же частичной специализацией [1]? Можно ли вообще специализировать прямо в классе или нужно выносить отдельно?
S>>Полной. Только перед T вроде typename писать полагается. O>Если можно, обоснование. Я тоже думаю, что полной, но вот хотелось бы быть 100% уверенным.
Таки я соврал. Это вообще не специализация.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
O>>[2] будет являться полной или же частичной специализацией [1]?
ПК>Согласно текущей версии стандарта это является ошибкой, т.к. шаблон члена шаблона класса не может быть специализирован без специализации шаблона содержащего класса (14.7.3/18).
Явно специализирован не может быть. К частичной специализации это не относится (см. пример в 14.5.4.3/2). Потому это и бросатеся в глаза как дефект, что для явной и частичной специализации заведены разные правила без каких-либо разумных оснований.
O>>Можно ли вообще специализировать прямо в классе или нужно выносить отдельно?
ПК>Шаблоны членов класса должны специализироваться вне тела класса (14.7.3/2).
Опять же, это относится только к явной специализации.
В данном примере, конечно, имеет место явная специализация, поэтому, согласно, текущему стандарту, пример ошибочен.
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>бросатеся в глаза как дефект, что для явной и частичной специализации заведены разные правила без каких-либо разумных оснований. <...> В данном примере, конечно, имеет место явная специализация, поэтому, согласно, текущему стандарту, пример ошибочен.
Это мы правильно делаем, что все время повторяем "в текущем стандарте" т.к. в следующей версии, скорее всего, это поправят; во всяком случае, будем надеяться.
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
O>>>[2] будет являться полной или же частичной специализацией [1]?
АТ>В данном примере, конечно, имеет место явная специализация, поэтому, согласно, текущему стандарту, пример ошибочен.
Как это может быть явной специализацией, если тип Т не задан?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Это мы правильно делаем, что все время повторяем "в текущем стандарте" т.к. в следующей версии, скорее всего, это поправят; во всяком случае, будем надеяться.
<...>
S>Как это может быть явной специализацией, если тип Т не задан?
Специализацией это является, потому что присутствует `template<>'. Отсутствие в объявлении специализированной функции `<T>' в данном случае (если бы можно было предоставлять явную специализацию шаблонов членов в теле шаблона класса) допустимо, т.к. согласно п. 14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
O>Под конструктор копирования это подходит если U == T ?
Сам себе и отвечаю:
12.8.2 (сноска 106)
Because a template constructor is never a copy constructor, the presence of such a template does not suppress the implicit declaration
of a copy constructor. Template constructors participate in overload resolution with other constructors, including copy constructors,
and a template constructor may be used to copy an object if it provides a better match than other constructors.
ПК><...>
S>>Как это может быть явной специализацией, если тип Т не задан?
ПК>Специализацией это является, потому что присутствует `template<>'.
Это не довод. Наличие template<> с тем же успехом может говорить, например, о синтаксической ошибке. В данном случае оно, IMHO, говорит только о том, что автор кода хотел, чтобы это было специализацией.
ПК>Отсутствие в объявлении специализированной функции `<T>' в данном случае (если бы можно было предоставлять явную специализацию шаблонов членов в теле шаблона класса) допустимо, т.к. согласно п. 14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
Ну и где здесь "can be deduced from the function argument type"? Типа аргумента-то нет, в отличие от примера в процитированном пункте стандарта.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте orangy, Вы писали:
O>А есть где-нибудь список "планируемых" исправлений для стандарта после immutability period?
Все зависит от того, что ты понимаешь под `immutability period'. Если ты имеешь в виду пятилетний period of stability (который уже истек), т.е. ожидаемые изменения стандарта, то их, естественно, еще никто не знает. Какие-то догадки можно делать, например, на основании дискуссий в comp.std.c++.
Если же ты имеешь в виду исправления, которые войдут в Technical Corrigenda, то Andrew Koenig где-то сообщал, что TC1 уже направлен в ANSI/ISO для утверждения и его можно ожидать в течение нескольких месяцев. Один из последних черновиков доступен: http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1316.
O>Дефект лист я видел только для STL <...> А для языка есть в публичном доступе?
Здравствуйте Sergey, Вы писали:
ПК>>Отсутствие в объявлении специализированной функции `<T>' в данном случае (если бы можно было предоставлять явную специализацию шаблонов членов в теле шаблона класса) допустимо, т.к. согласно п. 14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
S>Ну и где здесь "can be deduced from the function argument type"?
Чем изначальный пример в отношении специализации (кроме того, что она в нем не разрешена) отличается от следующего?
Здравствуйте Sergey, Вы писали:
ПК>>Отсутствие в объявлении специализированной функции `<T>' в данном случае (если бы можно было предоставлять явную специализацию шаблонов членов в теле шаблона класса) допустимо, т.к. согласно п. 14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
S>Ну и где здесь "can be deduced from the function argument type"?
Чем изначальный пример в отношении специализации (кроме того, что она в нем не разрешена) отличается от следующего?
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Здравствуйте Sergey, Вы писали:
ПК>>>Отсутствие в объявлении специализированной функции `<T>' в данном случае (если бы можно было предоставлять явную специализацию шаблонов членов в теле шаблона класса) допустимо, т.к. согласно п. 14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
S>>Ну и где здесь "can be deduced from the function argument type"?
ПК>Чем изначальный пример в отношении специализации (кроме того, что она в нем не разрешена) отличается от следующего?
ПК>
Здравствуйте Павел Кузнецов, Вы писали:
S>>>>Как это может быть явной специализацией, если тип Т не задан?
ПК>>>Специализацией это является, потому что присутствует `template<>'.
S>>Это не довод. Наличие template<> с тем же успехом может говорить, например, о синтаксической ошибке. В данном случае оно, IMHO, говорит только о том, что автор кода хотел, чтобы это было специализацией.
ПК>Это уже философский вопрос, чего хотел автор. Для компилятора важно, что получилось. Синтаксически `template < > declaration' (14.7.3), [2] является явной специализацией.
Признаю, это я проглядел. Тогда глядим в пункт 7.1:
declarationseq:
declaration
declaration-seq declaration
Я начинаю понимать все меньше Если я после template < > напишу namespacede-finition или block-declaration, это тоже синтаксически будет явной специализацией? Бред.
ПК>О семантике (времени компиляции в т.ч.) программ, содержащих диагностируемые ошибки рассуждать бессмысленно.
Согласен, софистика и интереса не представляет.
ПК>>>>>14.7.3/11 "A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type."
S>>>>Ну и где здесь "can be deduced from the function argument type"? ПК><...> S>>>>Типа аргумента-то нет, в отличие от примера в процитированном пункте стандарта.
ПК>>>Тип аргумента T.
S>>Это template type parameter класса foo, а не тип.
ПК>Шаблон класса порождает множество несвязанных классов, в каждом из которых template type parameter привязан к соответствующему template type argument, который является каким-то типом. Поэтому я и написал аргумента T. Например:
ПК>
ПК>template<class T>
ПК>class C
ПК>{
ПК> T t;
ПК>};
ПК>Следуя твоей логике можно было бы задать вопрос: "какого типа переменная t?". Да никакого, до тех пор, пока шаблон C не будет конкретизирован и template type parameter не будет привязан к какому-либо template type argument.
Чуть уточню — не никакого, а любого.
ПК>Точно так же и в приведенном примере шаблона foo T обозначает какой-то тип.
Именно — обозначает тип, а не является типом. Дополнительный уровень косвенности.
ПК>Выяснять какой бессмысленно до тех пор, пока шаблон foo не конкретизирован и template type parameter не привязан к template type argument. Когда это произошло, T обозначает тип соответствующего template type argument.
При специализации тип (часть типов) не надо выяснять — они содержатся в декларации. Поэтому я и утверждаю, что изначальный пример специализацией не является.
ПК>До тех же пор стандартом требуется, чтобы члены шаблона не порождались и, соответственно, подавляются всякие семантические проверки типа "provided it can be deduced from the function argument type", кроме тех, которые будут приводить к ошибкам при любых аргументах шаблона. Например, аналогично есть требование о том, что тип переменной должен быть законченным, или что два перегруженных метода класса должны иметь разные сигнатуры (т.е. разные соглашения о вызовах и/или типы аргументов и/или константность и т.п.). Однако эти правила в общем случае не могут быть проверены для членов шаблона класса:
ПК>
ПК>template<class T>
ПК>class C
ПК>{
ПК> void f(int);
ПК> void f(T);
ПК> T t;
ПК>};
ПК>поэтому проверка этих правил откладывается до конкретизации шаблона, а компилятор ограничивается проверкой синтаксиса.
Каким образом это касается обсуждаемого вопроса?
ПК>В примере шаблона foo с синтаксисом все в порядке. Поэтому, если бы не явные запреты, то исходный пример был бы верен, т.к. явная специализация функции-члена f порождалась бы, как и другие члены шаблона только при ее использовании. Я не вижу причин, почему компилятор не смог бы вывести необходимую информацию без `<T>' аналогично другим подобным случаям.
Может быть (я пока в этом не уверен), но под пункт 14.7.3/11 это никак бы не попадало — из аргументов функции тип выведен быть не может.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Sergey, Вы писали:
S>Признаю, это я проглядел. Тогда глядим в пункт 7.1: S>declarationseq: S> declaration S> declaration-seq declaration
S>declaration: S> block-declaration S> function-definition S> template-declaration S> explicit-instantiation S> explicit-specialization S> linkage-specification S> namespace-definition S>block-declaration: S> simple-declaration S> asm-definition S> namespace-alias-definition S> using-declaration S> using-directive S>simple-declaration: S> decl-specifier-seq(opt) init-declarator-list(opt) ;
S>Я начинаю понимать все меньше Если я после template < > напишу namespacede-finition или block-declaration, это тоже синтаксически будет явной специализацией? Бред.
Конечно бред. Это грамматика языка. Грамматика языка описывает только общий скелет синтаксиса языка. Описать все well-formed С++ программы при помощи только контекстно-свободной грамматики совершенно невозможно хотя бы потому, что существует большое количество конструкций, которые не описываются контекстно свободными грамматиками (возьми любую книгу по теории трансляции). Поэтому поверх грамматики на С++ программу накладывается еще ряд семантических правил, передваемых "на словах". Эти правила тоже должны выполняться. Вот эти-то дополнительные правила и запрещают писать namespace-definition или block-declaration после 'template<>'.
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>Конечно бред. Это грамматика языка. Грамматика языка описывает только общий скелет синтаксиса языка. Описать все well-formed С++ программы при помощи только контекстно-свободной грамматики совершенно невозможно хотя бы потому, что существует большое количество конструкций, которые не описываются контекстно свободными грамматиками (возьми любую книгу по теории трансляции). Поэтому поверх грамматики на С++ программу накладывается еще ряд семантических правил, передваемых "на словах". Эти правила тоже должны выполняться. Вот эти-то дополнительные правила и запрещают писать namespace-definition или block-declaration после 'template<>'.
Именно. Поэтому я и говорю, что если языковая конструкция начинается с template<>, она не обязательно является explicit-specialization, а вполне может быть просто ill-formed. И исходный пример
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) { ... } // [1]template<>
void f(const T &val) { ...} // [2]
};
по действие пунктов 14.7.3/18 или 14.7.3/2 не попадает, поскольку не является специализацией. Для специализации, IMHO, небходимо явное присутствие типа (а не template type parameter класса foo) в декларации функции.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
ПК>>template<class T>
ПК>>class C
ПК>>{
ПК>> T t;
ПК>>};
ПК>>Следуя твоей логике можно было бы задать вопрос: "какого типа переменная t?". Да никакого, до тех пор, пока шаблон C не будет конкретизирован и template type parameter не будет привязан к какому-либо template type argument.
S>Чуть уточню — не никакого, а любого.
Именно, что никакого: переменной еще нет. Даже класса, членом которого она могла бы быть тоже еще нет. Вот когда шаблон будет конкретизирован, тогда и класс появится, и переменная появится, и тип у нее будет.
ПК>>Точно так же и в приведенном примере шаблона foo T обозначает какой-то тип.
S>Именно — обозначает тип, а не является типом. Дополнительный уровень косвенности.
Нет там никакой косвенности. До тех пор, пока шаблон не конкретизирован, члена f просто не существует, равно как и содержащего его класса. Есть шаблон для образования бесконечного количества членов f бесконечного количества классов foo<...>. Объявления членов-функций появятся только при конкретизации содержащего шаблона. Определения — еще позже, только при использовании самих членов.
ПК>>Выяснять какой бессмысленно до тех пор, пока шаблон foo не конкретизирован и template type parameter не привязан к template type argument. Когда это произошло, T обозначает тип соответствующего template type argument.
S>При специализации тип (часть типов) не надо выяснять — они содержатся в декларации. Поэтому я и утверждаю, что изначальный пример специализацией не является.
Изначальный пример является шаблоном специализаций, так же как, например:
template<class T>
class C
{
int g() { }
};
g является шаблоном для порождения бесконечного кол-ва функций-членов бесконечного количества классов.
ПК>>поэтому проверка этих правил откладывается до конкретизации шаблона, а компилятор ограничивается проверкой синтаксиса.
S>Каким образом это касается обсуждаемого вопроса?
Еще раз: когда шаблон будет конкретизирован, `template<> f(const T&)' станет специализацией семантически, также как и в примере выше `int g()' станет объявлением функции-члена. До тех пор рассуждать о типах бессмысленно — это шаблоны функций-членов.
ПК>>В примере шаблона foo с синтаксисом все в порядке. Поэтому, если бы не явные запреты, то исходный пример был бы верен, т.к. явная специализация функции-члена f порождалась бы, как и другие члены шаблона только при ее использовании. Я не вижу причин, почему компилятор не смог бы вывести необходимую информацию без `<T>' аналогично другим подобным случаям.
S>Может быть (я пока в этом не уверен), но под пункт 14.7.3/11 это никак бы не попадало — из аргументов функции тип выведен быть не может.
Этот пункт, как и прочие семантические проверки, не применяется до тех пор, пока шаблон не конкретизирован и тип до тех пор тоже выводить не надо, также как и тип функции g в примере выше.
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Sergey, Вы писали:
АТ>>Поэтому поверх грамматики на С++ программу накладывается еще ряд семантических правил, передваемых "на словах". Эти правила тоже должны выполняться. Вот эти-то дополнительные правила и запрещают писать namespace-definition или block-declaration после 'template<>'.
S>Именно. Поэтому я и говорю, что если языковая конструкция начинается с template<>, она не обязательно является explicit-specialization, а вполне может быть просто ill-formed. И исходный пример
<...> S>по действие пунктов 14.7.3/18 или 14.7.3/2 не попадает, поскольку не является специализацией.
Еще раз: подобные семантические ограничения для шаблонов "включаются" только при конкретизации последних. Диагностировать их нарушение до этого компилятор может только если уверен, что не существует таких аргументов шаблона, при которых приведенные конструкции являются верными. Для нашего примера такие аргументы существуют.
S>Для специализации, IMHO, небходимо явное присутствие типа (а не template type parameter класса foo) в декларации функции.
Для объявления члена тип тоже должен быть полным, но это не проверяется до конкретизации шаблона.
<< J 1.0 alpha 5 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
S>>При специализации тип (часть типов) не надо выяснять — они содержатся в декларации. Поэтому я и утверждаю, что изначальный пример специализацией не является.
ПК>Изначальный пример является шаблоном специализаций, так же как, например:
ПК>
ПК>template<class T>
ПК>class C
ПК>{
ПК> int g() { }
ПК>};
ПК>g является шаблоном для порождения бесконечного кол-ва функций-членов бесконечного количества классов.
Так специализацией или "шаблоном специализаций"? Если второе (с чем я вполне согласен), то где про это написано в стандарте? IMHO, нет в языке такого.
ПК>Еще раз: когда шаблон будет конкретизирован, `template<> f(const T&)' станет специализацией семантически, также как и в примере выше `int g()' станет объявлением функции-члена.
IMHO, до конкретизации шаблона дело дойти не должно, поскольку исходный пример не является разрешенной языковой конструкцией.
ПК>До тех пор рассуждать о типах бессмысленно — это шаблоны функций-членов.
Во-во. А при explicit specialization типы присутствют сразу. Ясли это и не сказано нигде явно, то, IMHO, только потому что и так должно быть понятно.
ПК>>>В примере шаблона foo с синтаксисом все в порядке. Поэтому, если бы не явные запреты, то исходный пример был бы верен, т.к. явная специализация функции-члена f порождалась бы, как и другие члены шаблона только при ее использовании. Я не вижу причин, почему компилятор не смог бы вывести необходимую информацию без `<T>' аналогично другим подобным случаям.
S>>Может быть (я пока в этом не уверен), но под пункт 14.7.3/11 это никак бы не попадало — из аргументов функции тип выведен быть не может.
ПК>Этот пункт, как и прочие семантические проверки, не применяется до тех пор, пока шаблон не конкретизирован и тип до тех пор тоже выводить не надо, также как и тип функции g в примере выше.
Ладно, тогда скажи — если вот так переписать (дабы не обсуждать заведомо неправильный код), пример вдруг станет правильным? И будет являться explicit specialization?
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) {;} // [1]
};
template<> template<class T>
void foo<T>::f(const T &val) {;}
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Sergey, Вы писали:
S>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>Конечно бред. Это грамматика языка. Грамматика языка описывает только общий скелет синтаксиса языка. Описать все well-formed С++ программы при помощи только контекстно-свободной грамматики совершенно невозможно хотя бы потому, что существует большое количество конструкций, которые не описываются контекстно свободными грамматиками (возьми любую книгу по теории трансляции). Поэтому поверх грамматики на С++ программу накладывается еще ряд семантических правил, передваемых "на словах". Эти правила тоже должны выполняться. Вот эти-то дополнительные правила и запрещают писать namespace-definition или block-declaration после 'template<>'.
S>Именно. Поэтому я и говорю, что если языковая конструкция начинается с template<>, она не обязательно является explicit-specialization, а вполне может быть просто ill-formed. И исходный пример
S> S>
S>по действие пунктов 14.7.3/18 или 14.7.3/2 не попадает, поскольку не является специализацией. Для специализации, IMHO, небходимо явное присутствие типа (а не template type parameter класса foo) в декларации функции.
Откуда ты взял про это "явное присутствие типа"? И что именно ты имеешь в виду под "типом"?
С точки зрения грамматики (14.7.3/1) явная специализация представляет собой декларацию, предваренную 'template <>'. Все, что остается проверить, это является ли то, что следует за 'template <>' декларацией функции. Подозрения вызывает только декларация параметра функции. В декларации параметра функции требуется присутствие type-name. Такая декларация параметра функции — это ни что иное как simple-declaration. Из чего состоит simple-declaration можно последовательно посмотреть в 7/1, 7.1/1, 7.1.5/1 и 7.1.5.2/1.
Теперь заглянем в пункт 14.1/3. Этот пункт явно говорит, что типовой параметр шаблона являетсяtype-name. Вот, собственно, и все. Если в своем ИМХО под "типом" ты имел в виду именно это, то вот ответ на это твое ИМХО: твое ИМХО неверно, пункт 14.1/3 явно говорит, что 'T' в данном случае является "типом".
Надеюсь, все сомнения развеяны. Если бы не упоминавшееся ранее требование того, что явная специализация члена класса делается только снаружи класса и только для специализации самого класса, то эта декларация была бы совершенно правильной явной специализацией.
{чтобы не повторять уже сказанное, аргументы, аналогичные тем, что привел Андрей Тарасевич в соседнем письме, опущены}
ПК>>Изначальный пример является шаблоном специализаций, так же как, например: <...>
S>Так специализацией или "шаблоном специализаций"? Если второе (с чем я вполне согласен), то где про это написано в стандарте? IMHO, нет в языке такого.
Конечно, нет. Текущий стандарт запрещает явную специализацию членов без специализации шаблонов объемлющих классов. Но, синтаксически это является явной специализацией, помещенной в тело шаблона класса, что явно запрещается соответствующим пунктом стандарта. Семантически в результате это являлось бы шаблоном специализаций, так же как:
template<class T>
class C
{
int g();
};
Синтаксически g является объявлением функции, помещенным в тело шаблона. Семантически g является шаблоном членов классов, порожденных шаблоном C (см., например, 14.5.1.1/1 "declares three function templates." и т.п.).
ПК>>Еще раз: когда шаблон будет конкретизирован, `template<> f(const T&)' станет специализацией семантически, также как и в примере выше `int g()' станет объявлением функции-члена.
S>IMHO, до конкретизации шаблона дело дойти не должно, поскольку исходный пример не является разрешенной языковой конструкцией.
Опять двадцать пять. Конечно, в соответствии с текущим стандартом, до конкретизации дело не дойдет. Скажу больше — на некоторых компиляторах дело может не пойти дальше `template<>' просто потому что текущая версия стандарта не разрешает явной специализации в теле шаблона класса. Как только компилятор встретил `template<>' в подобном контексте, он сразу может выдавать сообщение об ошибке (Comeau):
"ComeauTest.c", line 8: error: explicit specialization is not allowed in the current scope
template<>
^
1 error detected in the compilation of "ComeauTest.c".
ПК>>До тех пор рассуждать о типах бессмысленно — это шаблоны функций-членов.
S>Во-во. А при explicit specialization типы присутствют сразу. Ясли это и не сказано нигде явно, то, IMHO, только потому что и так должно быть понятно.
Стандарт не имеет права, опускать места, которые "и так должны быть понятны". Но, снова-таки, п. 14.7.3/11 при обсуждении данного случая в контексте текущего стандарта вообще не имеет значения. К примеру, если мы перепишем пример так:
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) {;} // [1]template<>
void f<int>(constint &val) {;}
};
или так:
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) {;} // [1]template<>
void f(constint &val) {;}
};
он все равно будет содержать ошибку, т.к. предпринимается попытка специализации члена без специализации шаблона содержащего класса, а в двух последних случаях еще и в теле шаблона содержащего класса.
Медленно, по порядку: твои измышления о том, является ли template type parameter "типом" или нет, здесь не уместны, т.к. под argument type в 14.7.3/11 подразумевается не "конкретный тип" (int, char, class C и т.п.), а "то, как были объявлены параметры функции", чтобы убедиться в этом, можешь поискать сочетание "argument type" в 14.8, который, собственно и определяет правила вывода из типов параметров функций.
ПК>>>>если бы не явные запреты, то исходный пример был бы верен, т.к. явная специализация функции-члена f порождалась бы, как и другие члены шаблона только при ее использовании. Я не вижу причин, почему компилятор не смог бы вывести необходимую информацию без `<T>' аналогично другим подобным случаям.
S>>>Может быть (я пока в этом не уверен), но под пункт 14.7.3/11 это никак бы не попадало — из аргументов функции тип выведен быть не может.
Тип и не должен выводиться, должен выводиться отсутствующий аргумент шаблона из того, как объявлены параметры функции. Очевидно, что для компилятора между:
никакой разницы нет, т.к. опущенный аргумент '<T>' он вполне может вывести из объявления аргументов специализации. Hint: компиляторы, поддерживающие подобное в качестве расширения вполне счастливы, получая изначальный вариант:
ПК>>Этот пункт, как и прочие семантические проверки, не применяется до тех пор, пока шаблон не конкретизирован и тип до тех пор тоже выводить не надо, также как и тип функции g в примере выше.
S>Ладно, тогда скажи — если вот так переписать (дабы не обсуждать заведомо неправильный код), пример вдруг станет правильным? И будет являться explicit specialization?
S>
Вместо `template<> template<class T>' должно быть `template<class T> template<>', но даже при этом исправлении, на основании текущей версии стандарта приведенный пример не станет верным. И такой тоже:
template<class T>
class foo
{
public:
template<typename other>
void f(const other &val) {;} // [1]
};
template<class T> template<>
void foo<T>::f<T>(const T &val) {;}
По той же причине, что и два приведенных выше, в которых <T> изменено на <int>.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Sergey, Вы писали:
ПК>>До тех пор рассуждать о типах бессмысленно — это шаблоны функций-членов.
S>Во-во. А при explicit specialization типы присутствют сразу. Ясли это и не сказано нигде явно, то, IMHO, только потому что и так должно быть понятно.
При explicit specialization "сразу" присутствует type-name. Стандарт ясно говорит, что параметр шаблона (в данном случае — T) является type-name. Ничего более "конкретного", чем type-name, в explicit specialization не требуется.