Сообщение Re: Определение шаблона после использования от 03.04.2018 22:26
Изменено 03.04.2018 22:36 Constructor
AD>Почему этот код линкуется? Компилятор "собирает" запросы на инстанцирование?
AD>И должен ли по стандарту?
Де-юре этот код был не корректен до выхода C++11. См. Defect Report 993.
На данный момент место в стандарте, описывающее происходящее, выглядит так (см. главу Point of instantiation [temp.point], абзацы 1 и 8 в актуальной версии стандарта; выделение жирным мое):
1 For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
...
8 A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule (6.2), the program is ill-formed, no diagnostic required.
Т.е. имеем следующую картину:
#include <cstdio>
const char* name;
template<typename T>
void set_name(const char* n, T a);
void foo()
{
set_name("test", 11);
}
// первая точка инстанцирования специализации set_name<int>
// (в соответствии с абзацем 1, она "follows the namespace scope declaration or definition that refers to the specialization")
template<typename T>
void set_name(const char* n, T a)
{
name = n;
}
const char* get_name()
{
return name;
}
int main(int argc, char* argv[])
{
foo();
printf("%s\n", get_name());
return 0;
}
// вторая точка инстанцирования специализации set_name<int>
// (в соответствии с абзацем 8, "for any such specialization that has a point of instantiation within the translation unit,
// the end of the translation unit is also considered a point of instantiation")
AD>Почему этот код линкуется? Компилятор "собирает" запросы на инстанцирование?
AD>И должен ли по стандарту?
Де-юре этот код был некорректен до выхода C++11. См. Defect Report 993.
На данный момент место в стандарте, описывающее происходящее, выглядит так (см. главу Point of instantiation [temp.point], абзацы 1 и 8 в актуальной версии стандарта; выделение жирным мое):
1 For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
...
8 A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule (6.2), the program is ill-formed, no diagnostic required.
Т.е. имеем следующую картину:
#include <cstdio>
const char* name;
template<typename T>
void set_name(const char* n, T a);
void foo()
{
set_name("test", 11);
}
// первая точка инстанцирования специализации set_name<int>
// (в соответствии с абзацем 1, она "follows the namespace scope declaration or definition that refers to the specialization")
template<typename T>
void set_name(const char* n, T a)
{
name = n;
}
const char* get_name()
{
return name;
}
int main(int argc, char* argv[])
{
foo();
printf("%s\n", get_name());
return 0;
}
// вторая точка инстанцирования специализации set_name<int>
// (в соответствии с абзацем 8, "for any such specialization that has a point of instantiation within the translation unit,
// the end of the translation unit is also considered a point of instantiation")