C++中的多个模板的替代方案

4

我正在使用gcc 5.4.0开发一个C++11应用程序。在这个应用程序中,我有以下模板:

template <class T1, class T2, class T3>
class Operator
{
    T3* op1(T1* operand1, T2* operand2);
    T3* op2(T1* operand1, T2* operand2);
    T3* op3(T1* operand1, T2* operand2);
    T3* op4(T1* operand1, T2* operand2);
    //...
   T3* opn(T1* operand1, T2* operand2);
};

在 op1,op2,... opn 中,我需要处理一大堆数组(可能有数亿个元素)。例如算术运算、比较、复制等。我选择使用模板,因为我希望拥有像这样的结构:

#pragram omp parallel for
for(int64_t i = 0; i < length; i++)
{
    r[i] = operand1[i] /*operations here*/ operand2[i]
}

出于性能考虑,在for循环中嵌套if语句检查类型是没有意义的。而且,由于我想支持许多类型,例如(int8_t、int16_t、int32_t、int64_t、float和double,可能还有unsigned),如果为每个操作创建一堆for循环来处理每种类型的组合,我的代码将会变得非常臃肿。
问题在于,如果我想支持大约6到10种类型,编译器需要生成高达10^3个版本的代码。因为这足以满足T1、T2和T3的所有可能类型组合。
生成和编译所有这些代码需要很长时间。因此,我正在寻找一种不需要这么长时间进行编译并且不会增加太多开销的替代方案。我考虑使用多态,但我不知道如何获得类似的结果,主要是因为类型过载,我需要运算符:=、+、-、*、/、>、<等以某种方式与所有这些类型一起工作,而使用模板可以“自动”实现这些。
非常感谢任何指导。
编辑:我的应用程序将处理用户的数组,并将保留用户的数据(类型和布局)。这些数组可以是任何类型。因此,我可能需要添加int64_t和doubles或任何不同类型的组合。为了灵活性,我在应用程序中有一个代码路径,实例化所有可能的1000个组合(我使用递归宏实现了这一点)。因此,我真的在寻找一种方法,要么是减少即使有这么多模板也需要编译的时间,要么是将其更改为多态结构。
编辑2:经过一些调整(我的生成宏有一些小改进),我能够以O3编译约30分钟。这对于部署和分发来说还可以,但对于开发来说非常糟糕。因此,我将设置一个调试标志,并使用较少的类型支持(仅4或6个),这将大大减少编译时间。感谢所有的建议。

1
T1 is generally the same as T2 - Basile Starynkevitch
1
如果你询问的是类模板中的成员函数是否未被使用时不会被实例化,那么是的。 - Passer By
1
我建议将其编译为静态库,并在可执行文件中使用。这样,只有在出现新的操作符/操作数组合时才需要编译运算符。最终的可执行文件将仅包含实际使用的组合。 - king_nak
1
你是如何分发你的应用程序的?我认为你在应用程序中使用了“为了灵活性,我有一个代码路径,可以实例化所有可能的1000个组合”,这种做法可能会适得其反。如果你只让编译器实例化你使用的操作,那么速度会快得多。 - Caleth
1
如果你真的想要实例化这1000个版本,你可以分离声明和定义,并使用显式实例化。这样只有一个UT需要长时间编译,其他的将像普通函数一样调用模板函数... - Jarod42
显示剩余5条评论
1个回答

2

如果所有这些函数都要被实例化,避免代码膨胀的唯一解决方案是(如果可能的话)找到一个通用类型来执行操作,然后转换回特定类型:

common_type operator +(common_type,common_type);

template<class T1,class T2,class T3>
inline T1 operator +(T2 a, T3 b){
  return T1{common_type{a}+common_type{b}};
  }

使用范畴论术语,您需要找到(如果存在)从您定义的每个类(考虑它们是类别表示)到common_type类的一个morphism。这不是容易的任务,可能是不可能的。
也许一些中间步骤是可能的,如T1 operator+(common_type,common_type); ...

T3未使用。您的意思是从每种类型到另一种类型吗? - Passer By
@PasserBy,如果这是情况的话,这将是最佳解决方案,他甚至可以考虑将此常见类型用作其他类型的内部表示。但是,可能会有不同的常见类型,其中一些类别(例如Operator类)可能映射到其中一个。这里唯一有趣的事情是多对一的关系。 - Oliv
看起来我的代码可能需要一些努力,因为我基本上在处理数字类型。仍然需要评估由于转换而产生的性能影响。 - hlustosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接