Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shortest example to use templating function in C?

Tags:

c

syntax

How do I approach a function echo_tpl that can take 1 parameter of type int or string ,and print it out?

like image 682
httpinterpret Avatar asked Jan 28 '26 16:01

httpinterpret


1 Answers

C doesn't have templates. I think the best you could do is to use an union or to have the functions have different names. The latter way of having different names is the quasi-standard method of doing it (for instance fabs fabsf fabsl, also heavily used by OpenGL which also accounts for the fact C can't overload functions)

void echo_tpl_s(char const *string) { /* ... */ }
void echo_tpl_i(int number) { /* ... */ }

int main(void) {
  echo_tpl_s("Hello world");
  echo_tpl_i(42);
}

If there is a lot of common code, you may decide to factor it out in separate functions

void echo_tpl_s(char const *string) { 
  prepare_output_device();
  printf("%s", string);
  unprepare_output_device();
}

void echo_tpl_i(int number) { 
  prepare_output_device();
  printf("%d", number);
  unprepare_output_device();
}

Or you can take the union way, which will have the function names be equal but instead blow up the parameter type with meta informations.

enum Type {
  Number,
  String
};

struct Value {
  enum Type type;
  union { 
    int number;
    char const *string;
  } u;
};

void echo_tpl(struct Value value) {
  switch(value.type) {
    case Number: printf("%d", value.u.number); break;
    case String: printf("%s", value.u.string); break;
  }
}

int main(void) {
  echo_tpl((struct Value) { 
    .type = String, 
    .u.string = "Hello world" 
  });
}

The union way is particular well-suited if you want to store the value somewhere and then execute the print function without caring what value type you pass to it. In C89 you would need to create the value separately since it doesn't have compound literals

int main(void) {
  struct Value value;
  value.type = String;
  value.u.string = "Hello world";
  echo_tpl(value);
}

It's a good idea to create functions for that, though

struct Value stringval(char const *string) {
  struct Value value;
  value.type = String;
  value.u.string = string;
  return value;  
}

struct Value numberval(int number) {
  struct Value value;
  value.type = Number;
  value.u.number = number;
  return value;  
}

int main(void) {
  echo_tpl(stringval("Hello world!"));
}

Some compilers may provide extensions for writing such things. For instance Clang provides function overloading in C.

void echo_tpl(int value) __attribute__((overloadable)) {
  printf("%d", value);
}

void echo_tpl(char const *value) __attribute__((overloadable)) {
  printf("%s", value);
}

This solves the call-side of the function not to depend on the type. On the definition side, you still have to write the code twice. That's mainly because (as another answer explains) C doesn't have type-generic output functions. Of course if you use this feature, your code becomes nonportable.

like image 167
Johannes Schaub - litb Avatar answered Jan 31 '26 08:01

Johannes Schaub - litb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!