Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: template в многомодульном проекте C++
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
k155la3
Проект многомодульный, и полно "перекрестных" запросов из модуля в модуль.
В классе есть функция-метод, заданная шаблоном. Этот класс предполагаетс пользовать из других модулей.

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

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

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

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

Сергей Борщ
QUOTE (k155la3 @ Jan 11 2017, 14:22) *
Где должно располагаться "тело" функции, в hpp-файле или в cpp ?
В заголовочном файле.
QUOTE (k155la3 @ Jan 11 2017, 14:22) *
если это все (запросы к ф-ии из других модулей) проясняется уже на уровене линкера, и "докомпилировать" уже нельзя).
Нет, это разрешается на этапе компиляции. Линкер только из нескольких одинаковых реализаций в разных единицах трансляции оставляет одну.

В .cpp можно поместить специализацию, но в заголовочном файле в этом случае должно быть указано, что такая специализация существует.
k155la3
Цитата(Сергей Борщ @ Jan 11 2017, 15:31) *
В заголовочном файле.
. . . .

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

Имеется ввиду "использование" шаблона? т.е. в .cpp например объявляем переменную templClass<char> charTemplateVar;
Сергей Борщ
QUOTE (sigmaN @ Jan 12 2017, 11:07) *
Имеется ввиду "использование" шаблона? т.е. в .cpp например объявляем переменную templClass<char> charTemplateVar;

нет, имеется ввиду если есть заголовочный файл с шаблоном
CODE
template<typename T> void func(T & data) { data = 0; }
и мы хотим отдельный вариант для T = uint8_t
CODE
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".

Поэтому в заголовочный файл надо поместить
CODE
template<> void func(uint8_t & data);
а саму реализацию уже в .cpp:
CODE
template<> void func(uint8_t & data) { data = 1; }
k155la3
Цитата(sigmaN @ Jan 12 2017, 12:07) *
Имеется ввиду "использование" шаблона? т.е. в .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 ); пишем литерал
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.