在不同的文件中实例化模板

Templating template instantiation in different file

本文关键字:实例化 文件      更新时间:2023-10-16

我知道以下方法有效:

测试.h

#pragma once
#include <string>
class testclass
{
private:
    std::string _data;
public:
    template<class T> 
    testclass(const T&);
};

测试.cpp

#include "test.h"
template testclass::testclass(const int&);
template testclass::testclass(const long&);
//function can be called only with `int` and `long`
template<class T> 
testclass::testclass(const T &num)
    : _data(std::to_string(num))
{}

因此,这是拆分模板函数的声明和实现的一种成功方法,但也有一些缺点。其中之一是必须对所有类型进行硬编码,您希望用这些类型来调用函数,这是一种拖累。如果这个函数很小,那么你最终编写的代码比你没有模板化的时候要多…

我想知道这样的事情是否可能:

测试.cpp

#include "test.h"
template<class T2> //bogus syntax, but here the point of interest
template testclass::testclass(const T2&);
template<class T> 
testclass::testclass(const T &num)
    : _data(std::to_string(num))
{}

我想知道这样的事情是否可能:

不,那是不可能的。

您的选择是:

  1. testclass的每个用户都包含定义。

  2. 在一个包含定义的编译单元中定义testclass::testclass的每个所需实例。

没有其他选择。

为什么不在.h中直接在类上使用模板?

#pragma once
#include <string>
template <T>
class testclass
{
private:
    std::string _data;
public:
    testclass(const T& num) : data(std::to_string(num)) {}
};

这样,你就可以将你的类与你想要的任何类型一起使用,例如:

testclass<int> test(1);
testclass<double> test(2.0);
...

我认为这是不可能的,因为在编译阶段,编译器只能看到test.cpp文件,而不知道它必须实例化该模板的哪些类型。

因此,如果您只想为了模块化目的而将模板拆分为h/cpp文件,您可以尝试以下技巧:

  1. 将"test.cpp"文件重命名为"test.tpp"(*.tpp扩展名只是显示它是此处的模板类定义)
  2. 保持*.h文件不变,但在末尾添加#include"test.tpp"语句

可能您必须将includes从*.tpp移到test.h的头上,但我不确定,只需使用它即可。