解惑:如何在头文件中声明模板,并在源文件中定义模板?

我在初学C++模板时曾遇到一些问题。如果在头文件中声明一个模板类/函数,并且在源文件中对其进行定义,就比如说以下的代码

头文件 my_func.h

#pragma once
#include <iostream>

#ifndef MY_FUNC_H
#define MY_FUNC_H

template<typename T>
void my_func(const T& val);

#endif

源文件 my_func.cpp

#include "my_func.h"

void my_func(const T& val)
{
	std::cout<<val;
}

然而在主函数中调用它,却无法通过编译。VS发出了如下的错误:在这里插入图片描述
那么有没有解决办法呢?当然是有的,经过我的摸索,有以下几种解决办法。

1.直接定义

这是最简单粗暴的方法,那就是放弃分离定义和声明,直接都写在头文件中。

2.显式实例化模板

因为模板其实是在编译时并根据具体的类型对模板进行实例化,也就是说你想要调用的模板函数其实在编译时才生成了对应类型的函数。然而因为头文件和源文件分离,编译器无法得知你具体想要实例化的类型,所以才会出错。
解决的办法也很简单,就是在对应的源文件中显示实例化模板。
将源文件改为如下内容:

源文件 my_func.cpp

#include "my_func.h"

template <typename T>
void my_func(const T& val)
{
	std::cout << val;
}

template void my_func(const int&);

这样就能在主函数中顺利调用对应的类型的模板函数了

main.cpp

my_func<int>(100);

同样的,模板类也需要显示实例化。
但是!这样做的缺点也很明显,如果你像上文中一样更改源文件中的定义,那么你也只能调用对应类型的函数,也就是说你想要使用什么类型的模板都必须提前手动实例化,这样的模板简直是毫无意义,毕竟模板的优势不就是能处理任何类型的数据嘛。

3.使用模块

模块(module)是C++20中新引入的特性,具有更快更方便的优点。使用模块可以避免这类问题。如果想要在VS中开启模块,点击:项目->属性->常规->C++语言标准,选择C++20或者C++latest后点击“确定”。

模块接口 my_func.ixx

import <iostream>
export template <typename T>
void my_func(const T& val)
{
	std::cout << val;
}

使用“export”关键字模板声明定义一气呵成,确实很简单。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值