【问题标题】:How to replace C++ templates to be C compatible without changing the rest of the code?如何在不更改其余代码的情况下将 C++ 模板替换为 C 兼容?
【发布时间】:2020-02-10 14:53:25
【问题描述】:

我正在编写 C++ 编写的代码,并尝试将其转换为 C 以在嵌入式平台上构建。

我想知道如何在不更改其余代码的情况下有效地转换模板以在 C 中执行相同的功能。

这是我项目中的示例文件:

template <typename T,int width,int depth>
void relu(T arr[][width][depth],T layermap[][width][depth]){
     for(int k=0;k<depth;k++)
     {
       for(int j=0;j<width;j++)
       {
           for (int i=0;i<width;i++)
           {
              /*max*/
             layermap[i][j][k]=((arr[i][j][k]>0)? arr[i][j][k]:0);
           }
       }
     }

}

【问题讨论】:

  • 手动专门化所有模板(并准备很多其他工作)
  • 一个题外话,但我强烈建议将 for 循环反转为 i,j,k 而不是 k,j,i。然后它将访问具有热 CPU 高速缓存行的连续内存区域。性能提升将是显着的。
  • 准备复制很多代码。说真的,为什么要这样做?为什么不直接使用 C++ 代码并添加包装器以从 C 调用它?
  • @KareemAbdelmoniem "@RichardCritten 我怎么能做这样的事情?" - 需要大量繁重的手工工作。C++ 模板的发明是出于原因避免大量的手工工作。没有模板?欢迎回来手工工作。
  • @Jarod42 问题是多维数组(而不是指针的指针)不能在 C 中作为参数传递。 不,它是 C++ 不支持VLA。见stackoverflow.com/questions/48901482/…

标签: c++ c class oop embedded


【解决方案1】:

此模板函数不能用宏替换,因为 C 预处理器无法推导出 widthdepth 值。我能建议的最好的方法是将部分代码移动到 C 宏中,并在其之上添加一个 C++ 模板包装器。这将保持与现有 C++ 代码的兼容性,但 C 代码必须手动传递宽度和深度:

// C header
#define crelu(arr, layermap, width, depth) do { \
        for (int i=0;i<width;i++) \
            for(int j=0;j<width;j++) \
                for(int k=0;k<depth;k++) \
                    layermap[i][j][k]=((arr[i][j][k]>0)? arr[i][j][k]:0); \
    } while(0)
// c++ header
template <typename T,int width,int depth>
void relu(T arr[][width][depth],T layermap[][width][depth]) {
    crelu(arr, layermap, width, depth);
}

【讨论】:

  • 使用 VLA:void relu_int(int width, int depth, int arr[][width][depth], int layermap[][width][depth] )stackoverflow.com/questions/31870266/…
  • @AndrewHenle VLA 如果我们将T 换成int(或编写许多重载),则可以使用VLA
【解决方案2】:

函数模板不是函数。函数不能做函数模板所做的事情。函数集合可以做函数模板所做的事情(在某种程度上;函数集合缺少模板参数推导,但这只是语法糖)。在 C 中实现一组可比函数的严格方法是这样的:

void relu_float_1_1 (float arr[][1][1],  float layermap[][1][1]);
void relu_float_1_2 (float arr[][1][2],  float layermap[][1][2]);
// ... other sizes
void relu_double_1_1(double arr[][1][1], double layermap[][1][1]);
void relu_double_1_2(double arr[][1][2], double layermap[][1][2]);
// ... other sizes
// ... other types

您只需要编写您使用的那些。


也就是说,您通常不会在 C 中编写这样的函数。如果目标是将一种语言翻译成另一种语言,直接音译很少有好的结果。

一个更 C 风格的版本是在运行时传递维度:

void relu_float (int width, int depth, float       arr[][width][depth],
                                       float  layermap[][width][depth]);
void relu_double(int width, int depth, double      arr[][width][depth],
                                       double layermap[][width][depth]);
// ... other types

【讨论】:

    猜你喜欢
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 2021-07-13
    • 2021-08-23
    相关资源
    最近更新 更多