Генерируется ли объектный код для неиспользуемых методов класса шаблона?

У меня есть класс шаблона C++, который создается с тремя разными параметрами типа. Есть метод, который класс должен иметь только для одного из этих типов, и который никогда не вызывается с двумя другими типами.

Будет ли объектный код для этого метода сгенерирован трижды (для всех типов, для которых создается шаблон) или объектный код создается только один раз (для типа, с которым он фактически используется)?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
2 177
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Обычно да.

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

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

Также это будет во многом зависеть от используемого компилятора C++, потому что они не все одинаковы.

Ответ принят как подходящий

Виртуальные функции-члены создаются при создании экземпляра шаблона класса, но невиртуальные функции-члены создаются только в том случае, если они вызываются.

Это описано в [temp.inst] стандарта C++ (в C++ 11 это §14.7.1 / 10. В C++ 14 это §14.7.1 / 11, а в C++ 17 это §17.7.1 / 9. Выдержка из C++ 17 ниже)

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement (9.4.1), unless such instantiation is required

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

template <class T>
class Xyzzy
{
public:
    void CallFoo() { t.foo(); }  // Invoke T::foo()
    void CallBar() { t.bar(); }  // Invoke T::bar()

private:
    T t;
};

class FooBar
{
public:
    void foo() { ... }
    void bar() { ... }
};

class BarOnly
{
public:
    void bar() { ... }
};

int main(int argc, const char** argv)
{
    Xyzzy<FooBar>  foobar;    // Xyzzy<FooBar> is instantiated
    Xyzzy<BarOnly> baronly;   // Xyzzy<BarOnly> is instantiated

    foobar.CallFoo();         // Calls FooBar::foo()
    foobar.CallBar();         // Calls FooBar::bar()

    baronly.CallBar();        // Calls BarOnly::bar()

    return 0;
}

Это действительно, хотя Xyzzy :: CallFoo () не может быть создан, потому что не существует такой вещи, как BarOnly :: foo (). Эта функция часто используется как инструмент метапрограммирования шаблонов.

Обратите внимание, однако, что «создание экземпляра» шаблона напрямую не коррелирует с тем, сколько генерируется объектного кода. Это будет зависеть от реализации вашего компилятора / компоновщика.

Мы также должны отметить, что не все функции могут быть даже созданы, и это нормально, пока они не вызываются.

Matt Price 08.10.2008 19:18

Сделанный. Я думал об этом, когда сначала отвечал, но мне было лень написать полное объяснение.

Kristopher Johnson 08.10.2008 21:52

Можно ли пометить метод для принудительного создания экземпляра (т.е. предотвратить его оптимизацию), не делая его виртуальным? Спасибо!

Serge 07.08.2013 18:39

Думаю, это зависит от компилятора и настроек. Например, я считаю, что MSVC6 сгенерировал все, а VS2005 - нет. В спецификации говорится, что компилятор не должен этого делать, но в реальном мире это зависит от фактического компилятора (например, для MSVC6 есть много обходных путей). Компоновщик может удалить функции, на которые нет ссылок, если включен / opt: ref (для VS аналогичные параметры существуют для других компиляторов).

Старый добрый MSVC6 и шаблоны, ах дни ... ужас.

QBziZ 09.10.2008 00:59

Другие вопросы по теме