重写我在C ++中用C编写的generics函数的最佳方法是什么?

//Prints out a given array template  void print(T t) { for(int i = 0; i < t.size(); i++) { cout << t[i] << " "; } cout << endl; } 

我有一个想法,但它包括传递数组的大小。 有可能避免这种情况吗?

*更新感谢所有的答案/想法,但这个问题比我的snorkeler可以处理得更深。 我想用C语言重写我的C ++代码,因为它编写得很糟糕而且很慢。 我现在看到我有机会在C中让它变得更糟。我将在Python中从头开始重写它(性能被诅咒)。 再次感谢

如果你没有ELEMENTS,那就是

 #define ELEMENTS(a) (sizeof(a)/sizeof(*a)) 

然后,

 #define print_array(a, specifier) print_array_impl(a, specifier, ELEMENTS(a), sizeof(*a)) void print_array_impl(void* a, char* specifier, size_t asize, size_t elsize) { for(int i = 0; i < asize; i++) { // corrected based on comment -- unfortunately, not as general if (strcmp(specifier, "%d") == 0) printf(specifier, ((int*)a)[i]); // else if ... // check other specifiers printf(" "); } printf("\n"); } 

像这样使用

 print_array(a, "%d") // if a is a int[] 

并且,需要是数组名称,而不是指针(否则ELEMENTS将无法工作)

如果不传递该数组的大小,您无法知道数组的大小(除了在静态数组中使用sizeof操作)。 这是因为指向内存块的指针只会指向内存块的基础,从中可以知道内存数组/内存块的起始位置,但由于没有结束定义,因此无法确定内存块的位置结束。

  • 您需要为每个数组设置自己的长度并保留它,并将其与数组一起使用,如下所述:

    • 您可以创建一个新类型:
      struct _my_array {
        typename arr [MAX];
        int n;
     } my_array; 

    要么

      struct _my_array {
        typename * arr;
        int n;
     } my_array; 

    在这种情况下,您需要使用newmalloc动态分配一块内存,并在完成释放时使用deletefree (分别)释放内存。

    • 或者您可以通过函数简单地传递数组元素。
  • 另一种方法是使用数组类型的特殊终结符值,如果遇到则将其确定为数组的结尾。 在这种情况下,您无需保留大小。 例如,字符串'\0'终止,因此所有字符串函数都知道当char数组中遇到'\0'字符时,它会认为该字符串已结束。

UPDATE

因为这是一个通用函数,并且数组可以是任何类型,所以你能做的一件事就是这样:

 struct _my_generic_arr { void *arr; int n; int type; } my_generic_arr; 

填充此数组时,您可以使用任何类型。 要标识哪种类型,请在type组件中传递标识。 每个唯一值将确定arr指针实际指向的类型(实际上是要指向的预期类型)。 n将定义长度。 现在,根据不同的type值创建一个switch - caseif - else梯形图或嵌套,并根据需要处理数组。

在c中跟踪其他块中的数组的大小是不可能的,这是传递数组大小的更好选择。

另一种选择是声明一个全局变量,它具有大小并在函数Eg中使用该变量。

 int size= void main() { int arr[]; } void print(T t) { for(int i = 0; i < size; i++) { printf("%d ",t[i]) //assuming T as int } printf("\n"); } 

在C中,您需要传递两个附加参数:数组的大小(如您所述),以及指示如何将t [i]转换为字符串的某种方式。 要将t [i]转换为字符串,您可以创建自定义switch语句来解码可能的类型,将指针传递给将返回字符串指针的函数,或者您可以传递printf格式说明符(例如“%d”for整数)。

问题比你想象的要大。 如果你有一个大小为12的数组,你怎么知道该数组中的数据是什么? 它可以是3个字符*(在32位系统上),3个int32_t,甚至12个字符。 您无法知道如何解释数据。 您可以做的最好的是实现自己的v-table版本并将print或toString函数放入其中。

 typedef struct { void *array; size_t length; int element_width; printer_t to_string; } container; 

printer_t是一种描述函数指针的类型,该函数指针接受一个元素指针并返回一个字符串(如果你不想free字符串,则打印它)。 这在C中几乎不值得做。这并不意味着它无法完成。 不过,我要强调的是,这一切都不是为了暗示应该这样做。

函数本身看起来像这样:

 void print(container *thing) { size_t offset; int width; char *stringified; width = thing->element_width; for (offset = 0; offset * width < thing->length; offset += width) { stringified = thing->to_string(thing->array + offset); printf("%s ", stringified); free(stringified); } } 

这样做本质上是将一个struct转换为一个带有方法的函数指针的虚假类。 您可以更加面向对象,并将该方法放在要打印的类型中,并使其成为一个数组。 无论哪种方式,这都不是一个好主意。 C代表写作C.如果你试着用不同的语言写作,你最终会遇到各种各样可怕的东西。