Реализация многофайловых шаблонов - PullRequest
2 голосов
/ 21 декабря 2010

При использовании обычных функций объявление и определение часто разделяются на несколько файлов, например:

// Foo.h

namespace Foo
{
    void Bar();
}

.

// Foo.cpp

#include "Foo.h"

void Foo::Bar()
{
    cout << "Inside function." << endl;
}

Насколько я понимаю, это не может сделать с шаблонами.Объявление и определение не должны быть отдельными, потому что соответствующая форма шаблона создается «по требованию», когда это необходимо.

Итак, как и где шаблоны обычно определяются в многофайловом проекте, подобном этому?Моя интуиция заключается в том, что это будет в Foo.cpp, потому что именно там обычно находится «мясо» функций, но с другой стороны, это заголовочный файл, который будет включен.

Ответы [ 3 ]

4 голосов
/ 21 декабря 2010

Вам необходимо записать определения шаблонных методов в файл .hxx и включить его в конец файла заголовка (.hh), в котором вы его объявили..Cc / .cpp используется для определения не шаблонных методов.

Таким образом, у вас будет один .hh, один .hxx (включенный в конце .hh) и один .cc;так что, включая ваш шаблонный заголовочный файл класса, будет также включено его определение.

Пример:

// list.hh
#IFNDEF LIST_HH
# DEFINE LIST_HH

template <typename T>
class List
{
  void fun1(T a);

  void fun2();
}

# include "list.hxx"

#ENDIF

// list.hxx
#IFNDEF LIST_HXX
# DEFINE LIST_HXX

# include "list.hh"

template <typename T>
void List::fun1(T a)
{
   // ...
}

#ENDIF

// list.cc

#include "list.hh"

void List::fun2()
{
   // ...
}


// anywhere.cc

#include "list.hh"

// ...

EDIT

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

Но, поскольку файл * .hh включает файл * .hxx, каждый раз при простом объявлении шаблонанеобходимо, полная реализация идет с этим.И если для реализации требуются другие объявления, такие как std :: string, вы заставляете весь клиентский код анализировать заголовок строки.

Чтобы избежать создания экземпляров несколько раз (занимая время и пространство), вы можете ввести четвертый типфайла, * .hcc: файлы, которые должны быть скомпилированы один раз для каждого конкретного параметра шаблона.

См. также зависимости во время компиляции

EDIT2

Запись определения шаблона непосредственно в заголовочный файл называется модель включения .Это увеличивает стоимость включения заголовка.Не только потому, что мы добавили определение шаблона, но и потому, что мы включили заголовки (что угодно), которые представляют тысячи строк. Реальная проблема для важных программ для компиляции (речь идет о часах компиляции здесь) .Модель разделения

Источник

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

2 голосов
/ 21 декабря 2010

Я разочарован тем, что ни в одном ответе не упоминается, что стандарт C ++ позволяет отделить определение от декларации. Это выглядит так:

// Foo.h
export template<class T> T f();

// Foo.cpp
#include "Foo.h"

export template<class T> T f()
{
    // blah blah
}

К сожалению, компиляторы почти не поддерживают export . Comeau это тот, который делает.

Однако export удалено из C ++ в C ++ 0x.

2 голосов
/ 21 декабря 2010

Код шаблона остается в файле .hh.Нет смысла делать их отдельными файлами, хотя рекомендуется размещать определения после всех объявлений.

Когда компилятор генерирует код шаблона, он помечает его так, чтобы компоновщик зналчто создание экземпляра шаблона в одном модуле компиляции (т. е. файл .o) является точно таким же кодом, как и в другом модуле.Он сохранит один и отбросит остальные, а не выдает ошибку «множественно определенный символ».

Это верно для современных компиляторов с хорошей поддержкой шаблонов.В случае GCC, начиная с 2.8.(Я знаю, я написал много кода для gcc 2.7.2.2 до того, как они укротили компоновщик, и вам пришлось прыгать через обручи, чтобы сделать шаблоны правильными.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...