繁体   English   中英

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

[英]Avoid repetitive code in C++ templated functions

我有一组非常有限的实数类型(目前是floatdouble ),我希望我的数学库的所有函数都被模板化。 我希望这些将在 header 文件中前向声明:

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<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, ...);

此外,其中一部分需要通过与 C 兼容的 header 提供:

#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

我给出了最简单的 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, ...) };

这已经是完整doA function 声明的 8 次重复。 我的问题是如何减少重复次数并获得更简洁的代码而需要更少的输入? 例如,是否可以在不重复完整声明的情况下进行显式初始化?

我知道许多人选择将模板 function 实现直接放入 header 文件以避免前向声明和显式初始化,但 arguments 反对是:

  • 我确切地知道我支持哪些类型,并且集合非常有限。
  • 编译时间增加(尤其是微小更改的增量编译)。
  • 如果没有前向声明,依赖关系(doA 依赖于 doB 等等)变得更难维护。

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

您可以编写一个宏,它将为您想要的所有类型实例化您的 function。

BOOST_PP_SEQ_FOR_EACH 您的代码的示例应用程序可以是:

#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() {}

编译后可能会看到 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>)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM