C++ 避免在C+中重复代码+;模板函数

C++ 避免在C+中重复代码+;模板函数,c++,templates,C++,Templates,我有一组非常有限的实数类型(目前是float和double),我希望我的数学库的所有函数都被模板化。我希望在头文件中向前声明以下内容: template<typename R> void doA(task_t<R> t, ...); template<typename R> void doB(task_t<R> t, ...); template<typename R> void doC(task_t<R> t, ...);

我有一组非常有限的实数类型(目前是
float
double
),我希望我的数学库的所有函数都被模板化。我希望在头文件中向前声明以下内容:

template<typename R> void doA(task_t<R> t, ...);
template<typename R> void doB(task_t<R> t, ...);
template<typename R> void doC(task_t<R> t, ...);
模板无效doA(任务…);
模板无效doB(任务…);
模板作废单据(任务等);
在源文件中实现:

template<typename R> void doA(task_t<R> t, ...) { ... }
template<typename R> void doB(task_t<R> t, ...) { ... }
template<typename R> void doC(task_t<R> t, ...) { ... }
template void doA(task_t<float> t, ...);
template void doB(task_t<float> t, ...);
template void doC(task_t<float> t, ...);

template void doA(task_t<double> t, ...);
template void doB(task_t<double> t, ...);
template void doC(task_t<double> t, ...);
template void doA(task_t,…{…}
模板void doB(task_t,…{…}
模板无效文档(任务…{…}
并在这些源文件中显式初始化:

template<typename R> void doA(task_t<R> t, ...) { ... }
template<typename R> void doB(task_t<R> t, ...) { ... }
template<typename R> void doC(task_t<R> t, ...) { ... }
template void doA(task_t<float> t, ...);
template void doB(task_t<float> t, ...);
template void doC(task_t<float> t, ...);

template void doA(task_t<double> t, ...);
template void doB(task_t<double> t, ...);
template void doC(task_t<double> t, ...);
模板无效doA(任务…);
模板无效doB(任务…);
模板作废单据(任务等);
模板无效doA(任务…);
模板无效doB(任务…);
模板作废单据(任务等);
此外,需要通过与C兼容的报头提供其中的一个子集:

#ifdef __cplusplus
using taskr32_t = task_t<float>;
using taskr64_t = task_t<double>;
#else
typedef struct taskr32t *taskr32_t;
typedef struct taskr64t *taskr64_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif

void doAr32(taskr32_t t, ...);
void doBr32(taskr32_t t, ...);

void doAr64(taskr64_t t, ...);
void doBr64(taskr64_t t, ...);

#ifdef __cplusplus
}
#endif
\ifdef\uuucplusplus
使用taskr32\u t=task\u t;
使用taskr64\u t=task\u t;
#否则
类型定义结构taskr32t*taskr32\u t;
typedef结构taskr64t*taskr64_t;
#恩迪夫
#ifdef_uucplusplus
外部“C”{
#恩迪夫
无效doAr32(任务32_t,…);
无效doBr32(任务32_t,…);
无效doAr64(任务64_t,…);
无效doBr64(任务64_t,…);
#ifdef_uucplusplus
}
#恩迪夫

我给出了最简单的C++转发实现:

void doAr32(taskr32_t t, ...) { doA<float>(t, ...) };
void doBr32(taskr32_t t, ...) { doB<float>(t, ...) };

void doAr64(taskr64_t t, ...) { doA<double>(t, ...) };
void doBr64(taskr64_t t, ...) { doB<double>(t, ...) };
voiddoar32(taskr32_tt,…{doA(t,…)};
void doBr32(taskr32_t,…){doB(t,…)};
void doAr64(taskr64_t,…{doA(t,…)};
void doBr64(taskr64_t,…{doB(t,…)};
这已经是完整的
doA
函数声明的8次重复。我的问题是如何减少重复次数,以更少的输入获得更干净的代码?例如,是否可以在不重复完整声明的情况下显式初始化

我知道许多人选择将模板函数实现直接放入头文件,以避免前向声明和显式初始化,但反对的理由有:

  • 我确切地知道我支持什么类型,而且集合非常有限
  • 编译时间增加(尤其是对微小更改的增量编译)
  • 依赖项(doA依赖于doB等等)在没有前向声明的情况下变得更难维护

到目前为止,我最好的想法就是生成有关显式实例化和C兼容层的代码,这是所有恼人的重复发生的地方。对于这个问题,这是一个常见的解决方案吗?

您可以编写一个宏来实例化您想要的所有类型的函数

看。代码的示例应用程序可以是:

#include <boost/preprocessor/seq/for_each.hpp>

template <class T> class task_t {};

template<typename R> void doA(task_t<R> t) {}
template<typename R> void doB(task_t<R> t) {}
template<typename R> void doC(task_t<R> t) {}

#define MY_TYPES (int)(float)(double)(bool)

#define INSTANTIATE_FOR_TYPE(r, data, my_type) \
template void doA(task_t<my_type> t); \
template void doB(task_t<my_type> t); \
template void doC(task_t<my_type> t);


BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_FOR_TYPE, _, MY_TYPES)                                                                                                     

int main() {}
#包括
模板类任务{};
模板无效doA(任务{}
模板void doB(task_t){
模板无效文档(任务{}
#定义MY_类型(int)(float)(double)(bool)
#为类型(r、数据、我的类型)定义实例化类型\
模板无效doA(任务)\
模板无效doB(任务)\
模板作废单据(任务);
每个类型的BOOST\u PP\u SEQ\u(为类型、类型、我的类型实例化)
int main(){}
编译之后,您可能会看到所有类型的doABC都被实例化

nm a.out | c++filt | grep \ do
000000000040053c W void doA<bool>(task_t<bool>)
0000000000400527 W void doA<double>(task_t<double>)
0000000000400512 W void doA<float>(task_t<float>)
00000000004004fd W void doA<int>(task_t<int>)
0000000000400543 W void doB<bool>(task_t<bool>)
000000000040052e W void doB<double>(task_t<double>)
0000000000400519 W void doB<float>(task_t<float>)
0000000000400504 W void doB<int>(task_t<int>)
000000000040054a W void doC<bool>(task_t<bool>)
0000000000400535 W void doC<double>(task_t<double>)
0000000000400520 W void doC<float>(task_t<float>)
000000000040050b W void doC<int>(task_t<int>)
nm a.out | c++过滤器| grep\do
0000000000 40053C W无效doA(任务)
0000000000 400527 W无效doA(任务)
0000000000 400512 W无效doA(任务)
0000000000 4004FD W无效doA(任务)
0000000000 400543 W无效doB(任务)
0000000000 40052E W无效doB(任务)
0000000000 400519 W无效doB(任务)
0000000000 400504 W无效doB(任务)
0000000000 40054A W作废单据(任务)
0000000000 400535 W作废单据(任务)
0000000000 400520 W作废单据(任务)
0000000000 40050B W作废单据(任务)

您可以编写一个宏,该宏将为您想要的所有类型实例化您的函数

看。代码的示例应用程序可以是:

#include <boost/preprocessor/seq/for_each.hpp>

template <class T> class task_t {};

template<typename R> void doA(task_t<R> t) {}
template<typename R> void doB(task_t<R> t) {}
template<typename R> void doC(task_t<R> t) {}

#define MY_TYPES (int)(float)(double)(bool)

#define INSTANTIATE_FOR_TYPE(r, data, my_type) \
template void doA(task_t<my_type> t); \
template void doB(task_t<my_type> t); \
template void doC(task_t<my_type> t);


BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_FOR_TYPE, _, MY_TYPES)                                                                                                     

int main() {}
#包括
模板类任务{};
模板无效doA(任务{}
模板void doB(task_t){
模板无效文档(任务{}
#定义MY_类型(int)(float)(double)(bool)
#为类型(r、数据、我的类型)定义实例化类型\
模板无效doA(任务)\
模板无效doB(任务)\
模板作废单据(任务);
每个类型的BOOST\u PP\u SEQ\u(为类型、类型、我的类型实例化)
int main(){}
编译之后,您可能会看到所有类型的doABC都被实例化

nm a.out | c++filt | grep \ do
000000000040053c W void doA<bool>(task_t<bool>)
0000000000400527 W void doA<double>(task_t<double>)
0000000000400512 W void doA<float>(task_t<float>)
00000000004004fd W void doA<int>(task_t<int>)
0000000000400543 W void doB<bool>(task_t<bool>)
000000000040052e W void doB<double>(task_t<double>)
0000000000400519 W void doB<float>(task_t<float>)
0000000000400504 W void doB<int>(task_t<int>)
000000000040054a W void doC<bool>(task_t<bool>)
0000000000400535 W void doC<double>(task_t<double>)
0000000000400520 W void doC<float>(task_t<float>)
000000000040050b W void doC<int>(task_t<int>)
nm a.out | c++过滤器| grep\do
0000000000 40053C W无效doA(任务)
0000000000 400527 W无效doA(任务)
0000000000 400512 W无效doA(任务)
0000000000 4004FD W无效doA(任务)
0000000000 400543 W无效doB(任务)
0000000000 40052E W无效doB(任务)
0000000000 400519 W无效doB(任务)
0000000000 400504 W无效doB(任务)
0000000000 40054A W作废单据(任务)
0000000000 400535 W作废单据(任务)
0000000000 400520 W作废单据(任务)
0000000000 40050B W作废单据(任务)