2017-02-03 23 views
1

Почему функции шаблона не отображаются в LLVM-IR, если функция не вызывается при испускании LLVM IR из кода C++, в отличие от других типов функций (int, float ...), которые будут присутствовать в llvm иК пример: следующая функция func1 не показывает в LLVM IRПочему функции шаблона не отображаются в LLVM-IR?

template <class tmp> 
tmp func1() { 
    // ... 
} 

Но эта функция func2 всегда показывает в LLVM IR

int func2() { 
    // ... 
} 
+1

Это не функция * шаблона *. Это шаблон * функции *. Это не функция, а план будущей функции. Это совершенно несущественно.'func ' будет * функцией шаблона *, то есть шаблоном * функции * со всеми уже известными параметрами шаблона. Это * создает экземпляр * шаблона, заставляя его «материализоваться». – AnT

ответ

5

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

template<typename T> 
T foo() { /* ... */ } 

Это не выдаст никакого кода.

Но это с другой стороны:

template<typename T> 
T foo() { /* ... */ } 

int test() { 
    return foo<int>(); 
} 

Выведет код для обоих test и foo<int>.

Вы также можете вручную создать экземпляр шаблона, как это:

template int foo<int>(); 
4

Это связано с how C++ templates work. Поскольку компилятор не знает, что такое tmp, пока вы не вызовете функцию (точнее, при ее создании), она не знает, как писать для нее код. Например, рассмотрим следующий шаблон:

template <typename T> 
T add(T left, T right) { 
    return left + right; 
} 

Если T является целым числом, то тело функции является целым числом добавить. Если T - это двойной, это добавление с плавающей запятой. Если T - std::string, это вызов функции для std::string::operator+.

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


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

template <typename T> 
class Adder { 
    T add(T left, T right) { 
     return left + right; 
    } 
}; 

Adder<int> a; 

это еще бы не экземпляр Adder<int>::add даже если компилятор имеет всю информацию, чтобы знать, что add<int> потенциально интересен, потому что вы не на самом деле вызовите или иным образом создайте экземпляр.

 Смежные вопросы

  • Нет связанных вопросов^_^