Как заставить конкретный экземпляр шаблона C ++ для создания экземпляра? - PullRequest
46 голосов
/ 28 января 2010

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

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


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

есть:

template<class T>
OS_EXPORT_DECL class MyTmpl
{
    T *item1;
public:
    inline T *simpleGetT() { return(item1); } /* small inline code in here */ } 
    T *doSomeReallyBigMergeStuff(T *b); // note only declaration here
};

// *** implementation source file only seen inside library

template<class T>
MyTmpl<T>::doSomeReallyBigMergeStuff(T *b)
{
    ... a really big method, but don't want to duplicate it, 
        so it is a template ...
}

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

????? В частности, я создаю библиотеку для нескольких версий компиляторов MSC, GCC и Intel.

Ответы [ 6 ]

52 голосов
/ 28 января 2010

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

Формирование экземпляра выполняется путем явного предоставления всех типов:

template class std::vector<int>;

Comeaus FAQ по шаблону подробно описывает связанные с этим вопросы.

42 голосов
/ 28 января 2010

То, что вы также можете попробовать, это явная реализация:

template class vector<int>;                    // class
template int& vector<int>::operator[](int);    // member
template int convert<int,double>(double);      // function
1 голос
/ 28 января 2010

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

void force_int_instance() {
  Abstract<int> *a;
  a->some_method();
  a->some_other_method(1, 2, 3);
}

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

0 голосов
/ 28 января 2010

Я собираюсь ответить на то, что, по-моему, вы имели в виду, а не на то, что вы сказали.

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

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

http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/topic/com.ibm.vacpp6m.doc/language/ref/clrc16explicit_instantiation.htm

0 голосов
/ 28 января 2010

Если я правильно понимаю ваш вопрос, у вас есть шаблонный класс, и вы хотите заставить компилятор сгенерировать код для использования с каким-то конкретным типом. Например, вы можете убедиться, что в вашей программе существует код для std :: vector .

Лучший способ убедиться в этом - просто создать экземпляр класса:

void EnsureInstantiation()
{
    std::vector<int> intvector;
    std::vector<boo> boolvector;
    /// etc.
}

Хитрость в том, что вам даже не нужно вызывать EnsureInstantiation где-либо в вашем коде. Просто убедитесь, что он не статичен, иначе компилятор может оптимизировать его.

0 голосов
/ 28 января 2010

абстрактный класс не может быть создан. Вы, вероятно, хотите сделать что-то вроде:

Abstract *a = new Implementation(...);

Чтобы вызвать создание шаблона, вызовите шаблон с параметрами шаблона:

std::max<int>(...);
std::pair<int, string>(...);
...