Пример:
template<typename T>
class A {
void f() { std::cout << "f";}
};
...
A<int> a;
A<double> a;
Генерируется ли f
один или несколько раз (один раз для каждого экземпляра шаблона) в конечном двоичном файле после компиляции и связывания? Не могу найти это правило в стандарте. ИИ говорит, что он генерируется только один раз, но я ему недостаточно доверяю.
Стандарт не расскажет вам, что происходит в реальном двоичном файле, это детали реализации. Я ожидаю, что каждый экземпляр шаблона будет иметь свою собственную функцию.
Кажется, я не могу найти это правило в стандарте...». Стандарт не имеет дело с «исполняемым файлом». Поэтому вы не найдете такого правила в стандарте. Найдите абстрактную машину в стандарте.
@user12002570 user12002570 Я знаю, что это разные классы, это был не мой вопрос. ИИ с вами не согласен.
@токсический «ИИ с тобой не согласен...» Тогда ИИ не прав. Не используйте «ИИ» для изучения C++. Вместо этого используйте хорошие книги по C++
Вы можете поиграть с godbolt.org/z/GGeoqhP6Y и вы увидите, что возможно всё: два тела, отсутствие тела вообще. Что имеет смысл в вашем примере, так это то, что f
никоим образом не зависит от параметра шаблона и теоретически может быть взаимно объединен компилятором, но, как сказано в других комментариях, это деталь реализации, а не язык.
Вы можете использовать cppinsights
&A<int>::f != &A<double>::f
.
Не могу найти это правило в стандарте.
Стандарт не касается «исполняемого файла». Так что в стандарте вы ничего об этом не найдете. Также в C++ есть правило как если бы.
Генерируется ли
f
один или несколько раз?
Теперь объявления функций-членов создаются с помощью неявных экземпляров A<int>
и A<double>
. Но определения создаются только тогда, когда фактически используются функции-члены.
Это означает, что, поскольку A<int>
и A<double>
являются разными типами классов, будут созданы два разных объявления template<> void A<int>::f();
и template<> void A<double>::f()
функций-членов. В вашей программе не будет создано определение функции-члена, поскольку вы фактически не используете функции-члены.
Вы также можете использовать cppinsights, чтобы получить некоторое представление об этом. Вы заметите, что два объявления функций генерируются с помощью cppinsights, который использует clang.`
хотя cppinsight показывает, что будет две функции, компиляторы обычно объединяют идентичные функции в одну, чтобы уменьшить размер двоичного файла, и это становится настоящей проблемой при отладке.
@AhmedAEK Да, компилятор может использовать правило «как если бы». Поскольку стандарт не касается «исполняемых файлов», на вопрос («Кажется, я не могу найти это правило в стандарте») можно ответить так: «Стандарт не имеет дело с исполняемыми файлами, поэтому вы не найдете никаких правило стандарта относительно этого».
Стандарт не описывает структуру программы «в окончательном двоичном виде после компиляции и компоновки».
Может быть любое количество копий инструкций, соответствующих выводу символа f на стандартный вывод. Этим функциям может быть экспортировано 0, 1 или 2 символа.
Требуется, чтобы значения указателей &A<int>::f
и &A<double>::f
сравнивались неравными.
Мне было интересно узнать о равенстве указателей, этот ответ устранил сложности из-за оптимизации компилятора, что, конечно, снова все делает несколько запутанным.
@aasoo долгое время msvc не соответствовал требованиям в этом отношении
A<int>
иA<double>
— это два разных класса. Таким образом, у них будут разные функции-члены.