Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

Реализация не должна имплицитно создавать шаблон функции, шаблон переменной, член шаблон, не виртуальная функция-член, класс-член, статический член данных шаблона класса или подстановка оператора constexpr if (9.4.1), если это требование не требуется

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

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(). Эта функция часто используется в качестве инструмента метапрограммирования шаблона.

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

Ответ 2

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

Ответ 3

Обычно, да.

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

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

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