2015-06-23 4 views
10

Я спрашиваю себя, почему следующий код работает, а что спецификатор extern делает при инстанцировании baz_instance:Передача структуры шаблону с extern const. Для чего нужен экстерн?

struct baz { 
    int value; 
}; 

extern const baz baz_instance = {3}; 

template<baz const& b> 
int foo(){ 
    return b.value; 
} 

int main(){ 
    foo<baz_instance>(); 
    return 1; 
} 

Почему приведенный выше код компилировать в первую очередь, и почему она не компилируется больше, если extern спецификатор не указано? Что делает спецификатор extern в этом примере?

ответ

6

Это одна из частей стандарта, которая изменилась с C++ 03 на C++ 11.

В C++ 03, [temp.arg.nontype] гласит:

Шаблон-аргумент для не-типа, не-шаблон Шаблон-параметр должен быть одним из:

  • [...]
  • [...]
  • адреса объекта или функции с внешним связыванием, в том числе шаблонов функций и функциональных шаблоны идентификаторов, но за исключением членов нестатического класса, выраженным как & Ид выражения, где & не является обязательным, если название относится к функции или массива, или если соответствующий шаблон-параметр является ссылкой; или
  • [...]

В C++ 11, которые получили обновленные в результате issue 1155, хотя GCC до сих пор a bug в отношении такого поведения:

  • постоянное выражение (5.19), которое обозначает адрес полного объекта со статическим временем хранения и внешним или внутренним соединением или функцией с внешняя или внутренняя связь , включая функцию шаблоны и функции-шаблоны функций, но исключая нестатические члены класса, выраженные (игнорируя круглые скобки) как & id-expression, где id-выражение - это имя объекта или функции, за исключением того, что & может опускаться, если имя относится к функции или массиву и должно быть опущено, если соответствующий шаблон шаблона является ссылкой; или

В C++ 14, которые получили упрощена еще дальше и даже не упоминает о связи.

Что касается вашего конкретного вопроса, спецификатор extern добавляет внешнюю связь к baz_instance. Без него baz_instance имеет внутреннюю связь. В C++ 03 вам понадобилась внешняя связь, чтобы иметь тип шаблона типа non-type ссылочного типа. В C++ 11 вас больше нет - поэтому extern больше не нужен, и он компилируется без него.

0

Ключевое слово extern указывает, что переменная была определена в другом модуле компиляции (исходный файл).

Так что в вашем случае, bazдолжен быть определен в другом исходном файле и ехЬегп это способ сказать, что это переменная не определена в этом исходном файле, а в другую, и вы найдете его в течение сборник.

Ключевое слово extern означает «объявить без определения». Другими словами, это способ явно объявить переменную или принудительно объявить без определения.

+0

Как вы можете видеть из исходного кода, база не была определена в другом исходном файле. Кроме того, он не объяснил бы, почему экземпляр структуры можно передать шаблону с внешним, но не может без внешнего. – smoes

+0

См. Редактирование в моем ответе –

1

От 14.3.2.1 стандартные состояния:

Шаблон-аргумент для не-типа, не-шаблон Шаблон-параметр должен быть одним из:

  • адрес объекта или функции с внешняя связь, включая функциональные шаблоны и шаблоны функций, но исключая нестатические членов класса, выраженные как & id-expression, где & является опцией l если имя относится к функции или массиву, или если соответствующий шаблон шаблона является ссылкой;

От https://stackoverflow.com/a/643927/451600 от mweerden

1

extern ключевого слова означает, что она будет иметь внешнюю связь, другими словами символ будет экспортирована, когда блок перевода будет составлен. Поскольку ваш тип const, он по умолчанию имеет внутреннюю привязку (как будто он был объявлен static). Шаблоны не могут зависеть от типов, которые имеют только внутреннюю связь.

Я хотел бы узнать причину, почему, но кажется, что она потеряна для песков времени: Why did C++03 require template parameters to have external linkage?.