Перейти к содержанию
    

template в многомодульном проекте C++

Проект многомодульный, и полно "перекрестных" запросов из модуля в модуль.

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

 

Где должно располагаться "тело" функции, в hpp-файле или в cpp ?

 

(как шаблон "узнает" какие "сущности-реализации" кода шаблона-функции надо генерировать,

если это все (запросы к ф-ии из других модулей) проясняется уже на уровене линкера, и "докомпилировать" уже нельзя).

 

Я пришел к выводу, что код надо размещать в hpp-файле, который включается во все вызывающие модули.

 

Это так или нет ?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где должно располагаться "тело" функции, в hpp-файле или в cpp ?
В заголовочном файле.

если это все (запросы к ф-ии из других модулей) проясняется уже на уровене линкера, и "докомпилировать" уже нельзя).
Нет, это разрешается на этапе компиляции. Линкер только из нескольких одинаковых реализаций в разных единицах трансляции оставляет одну.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В заголовочном файле.

. . . .

Спасибо за инф. Все ясно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Имеется ввиду "использование" шаблона? т.е. в .cpp например объявляем переменную templClass<char> charTemplateVar;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется ввиду "использование" шаблона? т.е. в .cpp например объявляем переменную templClass<char> charTemplateVar;

нет, имеется ввиду если есть заголовочный файл с шаблоном

template<typename T> void func(T & data) { data = 0; }

и мы хотим отдельный вариант для T = uint8_t

template<> void func(uint8_t & data) { data = 1; }

то если мы эту полную специализацию поместим в заголовочный файл и заголовочный файл включим в несколько исходников, то получим ошибку линковки "multiple definition of `void func<unsigned char>(unsigned char&)'"

А если поместим ее в .cpp файл, то в других файлах эта специализация использована не будет, а в этом файле если она используется до определения, получим ошибку компиляции "error: specialization of 'void func(T&) [with T = unsigned char]' after instantiation".

 

Поэтому в заголовочный файл надо поместить

template<> void func(uint8_t & data);

а саму реализацию уже в .cpp:

template<> void func(uint8_t & data) { data = 1; }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется ввиду "использование" шаблона? т.е. в .cpp например объявляем переменную templClass<char> charTemplateVar;

 

Задача - писать в архив(ы) записи различных форматов соотв-их,
например, различным событиям или лог-записям.
Автоматизация/аналог ручного использования reinterpret_cast.


--------------- Events.hpp ------------------
class CLog
{
    . . . . .

        int Put_SER_PageFlash_E( int );  метод записи для событий вида LOG

    . . . . .
};



class CEvents32
{
    . . . . .

        int Put_SER_PageFlash_E( int );   метод записи для "флаговых" событий
    
    . . . . .
};

---------------- Archive.hpp --------------------
class CArchive
{
public:

    . . . . .

    . . . . .

    . . . . .

        template <typename TPL_EventT> int PutToArchive_B( int n, TPL_EventT * obj_ptr )        
        {
              a_page = buf_base + p_WR;
              ret_45 = AT45_PageIsEmpty( a_page , 264, 1);    // Empty == 1 ?
              if( ret_45 != 1 )    
                return(-200);        
              else
              {
                    ret_45 = obj_ptr->Put_SER_PageFlash_E( a_page );
                    if( ret_45 > 0 )
                    {
                        ForwardIndex();
                        return(1);
                    }
                    else
                        return(ret_45);
              }
        }

    . . . . 

    . . . . 

    CArchive( int r_size )    {  . . . . . };
    ~CArchive(void)    { };
};


----------- вызовы из модулей -------------
(1) модуль 1
// тип Type(EV_Alarm32_1) ==  CEvents32
retCode_2 = ARH_Event.PutToArchive_B( 0, &EV_Alarm32_1);  пишем флаги 32 бит


(2) модуль 2
// тип Type(EV_Log_1) ==  CLog
retCodeARH = ARH_Event.PutToArchive_B( 1, &EV_Log_1 ); пишем литерал

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...