Сообщение Инжектирование друзей класса в охватывающее пространство име от 10.01.2022 19:55
Изменено 10.01.2022 20:16 Андрей Тарасевич
Инжектирование друзей класса в охватывающее пространство имен
Пусть у нас есть такое определение шаблона класса
Если я попытаюсь инстанцировать такой шаблон для двух разных типов `T` в одной единице трансляции, я сразу получу от компилятора сообщение об ошибке из-за множественного определения функций `foo` и `bar`. Например
Это понятно.
Но что произойдет, если я сделаю два разных инстанцирования этого шаблона в разных единицах трансляции?
Обратите внимание, что `foo` и `bar` являются не шаблонными (template), но "шаблонизированными" (templated) inline-функциями. При этом я специально сделал определение `foo` не зависящим от параметра шаблона `T`, а определение `bar` — явно зависящим от параметра шаблона.
Я бы предположил, что определения `foo` в разных единицах трансляции соответствуют всем требованиям, налагаемым на определения inline-функций, то есть с `foo` все в порядке. А вот `bar`, из-за ее зависимости от `T`, нарушает эти требования. Соответственно на `bar` я буду иметь нарушение ODR, скорее всего с "no diagnostic required".
Правильны ли мои предположения?
template <typename T> struct S
{
friend void foo()
{
std::cout << "Hello World" << std::endl;
}
friend void bar()
{
T t{};
std::cout << t << std::endl;
}
};
Если я попытаюсь инстанцировать такой шаблон для двух разных типов `T` в одной единице трансляции, я сразу получу от компилятора сообщение об ошибке из-за множественного определения функций `foo` и `bar`. Например
int main()
{
S<int> a;
S<double> b;
}
In instantiation of 'struct S<double>':
error: redefinition of 'void foo()'
5 | friend void foo()
| ^~~
main.cpp:10:15: error: redefinition of 'void bar()'
10 | friend void bar()
| ^~~
Это понятно.
Но что произойдет, если я сделаю два разных инстанцирования этого шаблона в разных единицах трансляции?
Обратите внимание, что `foo` и `bar` являются не шаблонными (template), но "шаблонизированными" (templated) inline-функциями. При этом я специально сделал определение `foo` не зависящим от параметра шаблона `T`, а определение `bar` — явно зависящим от параметра шаблона.
Я бы предположил, что определения `foo` в разных единицах трансляции соответствуют всем требованиям, налагаемым на определения inline-функций, то есть с `foo` все в порядке. А вот `bar`, из-за ее зависимости от `T`, нарушает эти требования. Соответственно на `bar` я буду иметь нарушение ODR, скорее всего с "no diagnostic required".
Правильны ли мои предположения?
Инжектирование друзей класса в охватывающее пространство име
Пусть у нас есть такое определение шаблона класса
Если я попытаюсь инстанцировать такой шаблон для двух разных типов `T` в одной единице трансляции, я сразу получу от компилятора сообщение об ошибке из-за множественного определения функций `foo` и `bar`. Например
Это понятно.
Но что произойдет, если я сделаю два разных инстанцирования этого шаблона в разных единицах трансляции?
Обратите внимание, что `foo` и `bar` являются не шаблонными (template), но "шаблонизированными" (templated) inline-функциями. При этом я специально сделал определение `foo` не зависящим от параметра шаблона `T`, а определение `bar` — явно зависящим от параметра шаблона.
Я бы предположил, что определения `foo` в разных единицах трансляции соответствуют всем требованиям, налагаемым на определения inline-функций, то есть с `foo` все в порядке. А вот `bar`, из-за ее зависимости от `T`, нарушает эти требования. Соответственно на `bar` я буду иметь нарушение ODR, скорее всего с "no diagnostic required".
Правильны ли мои предположения?
template <typename T> struct S
{
friend void foo()
{
std::cout << "Hello World" << std::endl;
}
friend void bar()
{
T t{};
std::cout << t << std::endl;
}
};
Если я попытаюсь инстанцировать такой шаблон для двух разных типов `T` в одной единице трансляции, я сразу получу от компилятора сообщение об ошибке из-за множественного определения функций `foo` и `bar`. Например
int main()
{
S<int> a;
S<double> b;
}
In instantiation of 'struct S<double>':
error: redefinition of 'void foo()'
5 | friend void foo()
| ^~~
main.cpp:10:15: error: redefinition of 'void bar()'
10 | friend void bar()
| ^~~
Это понятно.
Но что произойдет, если я сделаю два разных инстанцирования этого шаблона в разных единицах трансляции?
Обратите внимание, что `foo` и `bar` являются не шаблонными (template), но "шаблонизированными" (templated) inline-функциями. При этом я специально сделал определение `foo` не зависящим от параметра шаблона `T`, а определение `bar` — явно зависящим от параметра шаблона.
Я бы предположил, что определения `foo` в разных единицах трансляции соответствуют всем требованиям, налагаемым на определения inline-функций, то есть с `foo` все в порядке. А вот `bar`, из-за ее зависимости от `T`, нарушает эти требования. Соответственно на `bar` я буду иметь нарушение ODR, скорее всего с "no diagnostic required".
Правильны ли мои предположения?