Шаблоны: Использовать предописания для сокращения времени компиляции?

Директива @helper была удалена , поскольку она была неполной и ее текущий дизайн не соответствовал новому «пути ASP.NET 5». Одна из причин заключается в том, что помощники должны быть объявлены в папке App_Code, в то время как ASP.NET 5 не имеет понятия специальных папок . Поэтому команда решила временно удалить эту функцию.

Планируется вернуть ее в будущем. Смотрите этот и этот .

26
задан 17 February 2009 в 03:09
поделиться

4 ответа

Вы не можете передать, объявляют "части" классов как этот. Даже если бы Вы могли, Вы должными быть все еще инстанцировать кода где-нибудь, таким образом, Вы могли связаться против него. Существуют способы обработать его, Вы могли сделать себя небольшой библиотекой с инстанцированиями общих контейнеров (например, вектор) и связать их в. Затем необходимо было бы только когда-либо компилировать, например, vector< int> однажды. Для реализации этого, необходимо будет использовать что-то как [1 110], по крайней мере, предполагая, что Вы придерживаетесь g ++ и явно инстанцируете шаблона в своем lib с [1 111]

<час>

Так, реальный рабочий пример. Здесь у меня есть 2 файла, a.cpp и b.cpp

a.cpp:

#include <vector> // still need to know the interface
#include <cstdlib>

int main(int argc, char **argv) {
  std::vector<int>* vec = new std::vector<int>();
  vec->push_back(3);
  delete vec;
  return EXIT_SUCCESS;
}

Поэтому теперь я могу скомпилировать a.cpp с [1 112]:

g++ -fno-implicit-templates -c a.cpp

Это даст мне a.o. Если я затем, я пытаюсь связать a.o, который я получаю:

g++ a.o
/usr/bin/ld: Undefined symbols:
std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)
void std::_Destroy<int*, std::allocator<int> >(int*, int*, std::allocator<int>)
collect2: ld returned 1 exit status

Отрицательный результат. Таким образом, мы обращаемся к b.cpp:

#include <vector>
template class std::vector<int>;
template void std::_Destroy(int*,int*, std::allocator<int>);
template void std::__uninitialized_fill_n_a(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, unsigned long, int const&, std::allocator<int>);
template void std::__uninitialized_fill_n_a(int*, unsigned long, int const&, std::allocator<int>);
template void std::fill(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&);
template __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > std::fill_n(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, unsigned long, int const&);
template int* std::fill_n(int*, unsigned long, int const&);
template void std::_Destroy(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, std::allocator<int>);

Теперь Вы говорите себе, откуда сделал все эти дополнительные шаблонные вещи, прибывшие? Я вижу template class std::vector<int>, и это прекрасно, но что относительно остальной части его? Хорошо короткий ответ - то, что, эти вещи реализации при необходимости немного грязны, и когда Вы вручную инстанцируете их, следовательно часть этого беспорядка просачивается. Вы, вероятно, задаетесь вопросом, как я даже выяснил то, чего я должен был инстанцировать. Хорошо я использовал ошибки компоновщика ;).

Поэтому теперь мы компилируем b.cpp

g++ -fno-implicit-templates -c b.cpp

, И мы получаем b.o. Соединение a.o и b.o мы можем добраться

g++ a.o b.o

Ура, никакие ошибки компоновщика.

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

c.h

template<typename T>
class MyExample {
  T m_t;
  MyExample(const T& t);
  T get();
  void set(const T& t);
};

c.cpp

template<typename T>
MyExample<T>::MyExample(const T& t) : m_t(t) {}
template<typename T>
T MyExample<T>::get() { return m_t; }
template<typename T>
void MyExample<T>::set(const T& t) { m_t = t; }

a.cpp

 #include "c.h" // only need interface
 #include <iostream>
 int main() {
   MyExample<int> x(10);
   std::cout << x.get() << std::endl;
   x.set( 9 );
   std::cout << x.get() << std::endl;
   return EXIT_SUCCESS;
 }

b.cpp, "библиотеке":

 #include "c.h" // need interface
 #include "c.cpp" // need implementation to actually instantiate it
 template class MyExample<int>;

Теперь Вы компилируете b.cpp в b.o однажды. Когда a.cpp изменяет Вас, просто должен перекомпилировать это и ссылку в b.o.

35
ответ дан Logan Capaldo 15 October 2019 в 07:29
поделиться

Предописания позволяют Вам сделать это:

template <class T> class vector;

Затем можно объявить ссылки на и указатели на vector<whatever>, не определяя вектор (без включения vector заголовочный файл). Это работает то же предописаниями регулярных (нешаблон) классы.

проблема с шаблонами в особенности состоит в том, что Вам обычно нужны не только объявление класса, но также и все определения метода в Вашем заголовочном файле (так, чтобы компилятор мог инстанцировать необходимых шаблонов). Явное шаблонное инстанцирование (из которого можно вызвать использование с -fno-implicit-templates) является обходным решением для этого; можно поместить определения метода в исходный файл (или, следуя примеру Google Style Guide , в -inl.h заголовочный файл, который Вы не должны включать) затем явно инстанцируют их как это:

template <class int> class vector;

Примечание, в котором Вы на самом деле не нуждаетесь -fno-implicit-templates для пользы из этого; компилятор тихо постарается не инстанцировать любых шаблонов, для которых он не имеет никаких определений, при условии, что компоновщик поймет это позже. И добавление -fno-implicit-templates сделает использование весь шаблоны тяжелее (не только трудоемкие), таким образом, я не рекомендовал бы это.

проблема с Вашим примером кода состоит в том, что Вы вперед не объявляете истинное std::vector класс. Не включая <vector>, Вы создаете свое собственное, нестандартное vector класс, и Вы никогда не определяете push_back, таким образом, нет ничего, чтобы компилятор инстанцировал.

я привык предварительно скомпилированные заголовки для большого эффекта; я не уверен, почему они не помогли Вам. Вы помещаете все свои неизменяющиеся заголовки на сингле all.h, предварительно скомпилировал его и проверил с [1 113] или подобный, что all.h.pch был загружен, и отдельные заголовочные файлы не были? (Как использовать strace: вместо того, чтобы работать g++ mytest.cc, выполнение strace -o strace.out g++ mytest.cc, затем просматривают strace.out в текстовом редакторе и ищут open( вызовы для наблюдения, какие файлы читаются.)

22
ответ дан Josh Kelley 15 October 2019 в 07:29
поделиться

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

6
ответ дан gix 15 October 2019 в 07:29
поделиться

Существует <iosfwd>, который даст Вам некоторое предописание для iostream классов, но в целом нет очень, можно сделать о шаблонах stl с точки зрения вперед объявления их.

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

Посмотрите этот вопрос для других идей об ускорении компиляции.

3
ответ дан Community 15 October 2019 в 07:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: