2015-03-02 1 views
0

N4296::14.7.1/1 [temp.inst] приводится следующий пример:декларация, которая соответствует определению в шаблоне

template<class T, class U> 
struct Outer { 
    template<class X, class Y> struct Inner; 
    template<class Y> struct Inner<T, Y>; // #1a 
    template<class Y> struct Inner<T, Y> { }; // #1b; OK: valid redeclaration of #1a 
    template<class Y> struct Inner<U, Y> { }; // #2 
}; 
Outer<int, int> outer; // error at #2 

и следующее объяснение дано:

Outer<int, int>::Inner<int, Y> находится в #1b повторно объявлен. (Это не , но определено как связанное с определением в Outer<T, U>.) #2 также является переделкой #1a. Он отмечен как , связанный с определением, поэтому он является недопустимым повторным описанием той же частичной специализации .

Я был смущен тем, что #1b рассматривается как декларация, но не определение. Мы явно снабдили там тело функции и почему это еще не определение? На самом деле, вы не могли бы объяснить это выражение.

ответ

3

Это объясняется в тексте, непосредственно предшествующем примеру!

неявной конкретизацией шаблона класса специализации вызывает неявное создание экземпляров деклараций, но не из определений или аргументов по умолчанию функций членов класса, классы членов, область действия перечислений членов, статические элементы данных и шаблоны членов ; и это приводит к неявному созданию определений индексированных имен элементов и анонимных союзов участников. Однако для определения того, является ли инстанцированное переопределение члена действительным в соответствии с 9.2, декларация, соответствующая определению в шаблоне, считается определением .

Существует различие между определением функции, которое возникает в результате создания экземпляров шаблонов, и определения самих шаблонов функций.

+0

Можем ли мы определить частичную спекализацию шаблона, который мы хотим? И я до сих пор не понимаю, почему [этот код] (http://coliru.stacked-crooked.com/a/0dbfa72ad5ee9521) работает нормально. Не могли бы вы объяснить? –

0

Имя вводится в область действия с его первым объявлением и затем ассоциируется с объектом, таким как объект, функция или класс. В определенных областях, таких как область пространства имен или область класса, имя может быть объявлено несколько раз. Объявление имени может также включать определение именованного объекта. После того как определение будет видно, говорится, что рассматриваемая декларация связана с определением. Для именованного объекта допускается не более одного определения.

Когда шаблон класса создается неявно, определения его вложенных функций, классов и статических членов объекта не создаются немедленно. Они только создаются, как только они понадобятся. Тем не менее, существует специальное правило для обнаружения потенциальных конфликтов определения.

В этом примере в шаблоне класса с двумя параметрами, T и U, шаблон внутреннего класса с двумя параметрами, и XY, объявляется. Для внутреннего класса определены две частичные специализации: одна для случая, когда X совпадает с T, а другая для случая, когда X совпадает с U. Первая частичная специализация сначала объявляется в # 1a, а затем обновляется и ассоциируется с определением в # 1b. Вторая частичная специализация объявлена ​​и связана с определением в # 2.

Пока все хорошо.

Но что, если T и U - это тот же тип, например, int? В таком случае для любого заданного Y объявления в # 1a, # 1b и # 2 объявляют одно и то же имя, Outer<int, int>::Inner<int, Y>. Две из этих деклараций связаны с определениями и создают конфликт. Пример в N4296, который вы цитируете, состоит в том, чтобы продемонстрировать, что конфликт должен быть диагностирован, даже если нет ссылок, требующих создания Outer<int, int>::Inner<int, Y>.

Outer<int, char> прекрасно, потому что в этом случае T и U не совпадают и, следовательно, # 2 дает определение к Outer<int, char>::Inner<char, Y> который отличается от Outer<int, char>::Inner<int, Y> определены в # 1b.

+0

_ «Первая частичная специализация сначала объявляется в # 1a, а затем обновляется и дается определение в # 1b». _ Но цитата буквально говорит, что # 1b не является определением. Вот о чем идет речь. –