Есть ли возможность иметь одну версию машинного кода для всех аргументов шаблона шаблонной функции? - PullRequest
5 голосов
/ 20 ноября 2010

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

template<size_t num>    
struct Elements{
 public:
  SomeType elements[num];
};

template<size_t num>
void print(const Elements<num> & elements,size_t size){
 //all instances do exactly same thing and with regard to Size that determines the size of object
}

и, конечно, также есть версия по значению:

template<size_t num>
void print(const Elements<num> elements,size_t size){
 //all instances do exactly same thing and with regard to Size that determines the size of object
}

Ответы [ 3 ]

5 голосов
/ 20 ноября 2010

Умный компоновщик может распознать, когда два разных тела функций идентичны, и объединить их в один символ.В MSVC это называется «сворачивание КОМДАТА» и «удаление дубликатов» в большинстве других мест.Например, следующие две функции могут компилироваться одинаково на PPC, хотя они принимают разные типы, потому что типы имеют одинаковый размер и ведут себя одинаково в данной ситуации.

template<typename T>
GetLowBit( T foo ) { return T & 1; }

GetLowBit<unsigned long>(ulong x); // compiles to "li r4, 1 ; and r3, r3, r4 ; blr "
GetLowBit<signed long>(long x); // also compiles to "li r4, 1 ; and r3, r3, r4 ; blr "

и поэтому компоновщик может сделать обаих «имена» указывают на то же место, как и раньше, так что звонок на GetLowBit<unsigned long> идет на тот же адрес, что и звонок на GetLowBit<signed long>.Таким образом, в общем случае можно сложить различные экземпляры шаблонов функций, которые все работают с одинаковыми типами размеров одинаковыми способами.(В частности, контейнеры, в которых хранятся указатели или перечисления, как правило, складываются вместе.)

Это не просто для функций шаблона.Некоторые компоновщики могут заметить, когда любые две функции имеют идентичные тела, и объединить их.В частности, я вижу, что MSVC имеет тенденцию сворачивать каждую виртуальную функцию, которая не делает ничего, кроме возврата в одну uber-функцию, например, для

class A
{ 
  virtual void nothing() {};
}

class B
{
   virtual void empty() {};
}

Я часто вижу (в дизассемблере во время отладки чего-то еще), что записи vtableдля nothing и empty оба указывают на одно и то же тело функции, которое, в свою очередь, является просто ret.

Можете ли вы рассчитывать на это?Нет. Это функция, которую интеллектуальный компоновщик может предоставлять для функций , когда он их замечает .Ваш компоновщик может быть глупым - там много паршивых компиляторов.Это может произойти, только если вы предоставите определенные аргументы команды.Это может произойти для некоторых функций, но не для других по причинам, известным только компоновщику.Он может даже отличаться от сборки к сборке в зависимости от того, что еще есть в программе.

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

0 голосов
/ 20 ноября 2010

Относительно вашего конкретного запроса : Если мне нужен шаблонный класс, в котором большинство функций не различаются по аргументу шаблона, я обычно делаю базовый класс без шаблона.Это позволяет мне переместить большинство моих методов в файл .cc вместо заголовка и убедиться, что копии функций не распространяются неожиданно.

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

0 голосов
/ 20 ноября 2010

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

...