C++ template class/function, separate header file from source file

Separate source files containing templates from header files

The key lies in the explicit instantiation of the template.

solution

Template function to separate source files

  1. Write .hand .cppfile in the usual way , but pay attention to the added template <typename T>statement;
  2. At the .cppend of the file, add template 显式实例化code, such as:
// 显式实例化,注意,`template`之后没有`<>`,若添加则会报错!
// 每种将被使用的类型,均需要进行显式实例化
template void A::show(int &&);
template void A::show(double &&);
template void A::show(bool &&);

Template class separate source file

  1. Write the template class .hand .cppfile separately , pay attention to the added template <typename T>statement;
  2. At the .cppend of the file, add the 显式实例化code of the class , such as:
// 只需要class的显式实例化即可,不需要再写其成员函数的显式实例化代码
template class Base<QLabel>;
  1. At the .hend of the file of other classes that use this template class , add the external template class 显式实例化声明(just one more externkeyword):
// 添加这行代码的目的,其实是为了消除编译警告。即便删掉它,也不会导致编译错误
extern template class Base<QLabel>;

The previous is a brief description of the method of separating the source file and header file of the template function/class. It is inevitable that there are omissions. If you still have questions, you can continue to look at specific cases.


Sample code

Template function

  • t.h
#ifndef _T_H
#define _T_H

class A
{
    
    
public:
        template <typename T>
        void show(T &&t);
};

#endif // _T_H
  • t.cpp
#include "t.h"
#include <iostream>
using namespace std;


template <typename T>
void A::show(T &&t)
{
    
    
        string info = typeid(t).name();
        cout << info << endl;
}

// 显式实例化,注意,`template`之后没有`<>`,若添加则会报错!
template void A::show(int &&);
template void A::show(double &&);
template void A::show(bool &&);
  • main.cpp
#include <iostream>
#include "t.h"
using namespace std;


int main()
{
    
    
        A a;
        a.show(1);
        a.show(3.4);
        a.show(true);
}

Just compile directly:

a: t.cpp main.cpp
	g++ $^ -o $@ -std=c++17

run:

./a
​```output
i
d
b
​```end

Template class

Template class (base class)

  • head File
#include <QObject>
class QLabel;

template <typename T>
class Base : public QObject
{
    
    
public:
    Base(QObject *parent = nullptr);
    virtual ~Base() override;

    void add(T *t);
    void remove(T *t);
    void remove(int idx);
    T *find(int idx) const;
    
protected:
    QList<T *> _listItems;

};
  • Source File
#include "base.h"
#include <QLabel>


template <typename T>
Base<T>::Base(QObject *parent)
    : QObject(parent)
{
    
    
    // Do nothing
}

template <typename T>
Base<T>::~Base()
{
    
    
    qDeleteAll(_listItems);
    _listItems.clear();
}

template <typename T>
void Base<T>::add(T *t)
{
    
    
    _listItems.append(t);
}

template <typename T>
void Base<T>::remove(T *t)
{
    
    
    _listItems.removeAll(t);
}

template <typename T>
void Base<T>::remove(int idx)
{
    
    
    _listItems.removeAt(idx);
}

template <typename T>
T *Base<T>::find(int idx) const
{
    
    
    return _listItems.at(idx);
}


/************************************ Explicit Instantiate *****************************/
template class Base<QLabel>;

Ordinary derived class of template class

  • head File
#include "base.h"
class QLabel;

class Son : public Base<QLabel>
{
    
    
public:
    Son(QObject *parent = nullptr);
    virtual ~Son() override;

protected:
    void init();

};

/********************************** Explicit Instantiate *****************************/
extern template class Base<QLabel>;

  • Source File
#include "son.h"
#include <QLabel>

Son::Son(QObject *parent)
    : Base<QLabel>(parent)
{
    
    
    init();
}

Son::~Son()
{
    
    
    // Do nothing
}

void Son::init()
{
    
    
    add(new QLabel());
    remove(new QLabel);
    remove(123);
    find(321);
}


Ways to eliminate compiler warnings from template-derived classes

  1. At the cppend of the file of the template class base class , add explicit instantiation code:
template class Base<QLabel>;
  1. At the .cppbeginning of the file of the template class base class , add an include file:
#include <QLabel>
  1. .hAdd the external declaration code at the end of the file of the template class general derived class :
extern template class Base<QLabel>;

Guess you like

Origin blog.csdn.net/gkzscs/article/details/108662174