0

動作がすべて似ている一連の関数のC++ラッパーを作成したいと思います。しかし、それらはすべて異なる数の引数を持っています。たとえば(typeA、typeBなどが異なるtypedefされたタイプであると仮定します):

typeA func1 (typeB b, typeC c);

typeA func2 (typeB b, typeD d, typeE e);

これらは、ラッパーを作成したい関数です(どちらも戻り型typeAと型Bの最初の引数を持っていることに注意してください)。したがって、一般的なラッパークラスを作成し、引数のリストをコンストラクターに格納するつもりです。そして、次のように「func」のような関数を呼び出せるようにしたいと思います。

class wrapper {
  public:
    wrapper (/*args - a list of arguments, including 
               a pointer to the actual function, and 
               the remaining arguments depending 
               on the function. */);
    void func (typeB b, typeA &a);
}

したがって、コンストラクターに渡された引数を使用して関数(func1またはfunc2)を呼び出すようにfuncを記述したいと思います。

func1またはfunc2を可変数の引数があるかのように扱う方法があるかどうか知りたいです。または、少なくとも、C ++に関数と引数のリストを入力して、eval(function、argument_list)を取得する方法がある場合。

別の方法は、すべての関数のラッパーを作成することです。これは避けたいのですが、嫌いではありません。(また、解決策にラッパークラスではなくラッパー関数を使用することが含まれるかどうかは気になりません)

4

1 に答える 1

0

これが私がCで行ったことで、関数をラップアラウンドします。それがあなたを助け/刺激することを願っています。主な制限は、関数のシグネチャを変更する必要があるため、ユーザー定義関数のみをラップできることです。

私のソリューションはva_arg構造を使用しています。

#include <stdarg.h>
void * super_wrapper( void * (*fn)(), void * ret, int n, ...)
{
  va_list = my_list;
  va_start(my_list, n);
  ret = (*fn)(ret, n, my_list);
  va_end(my_list);
  return ret
}

ラッパーの署名は、実行する関数へのポインター、戻り値を取得するために関数に与えるポインター、関数への呼び出しの引数の数、そして実行する関数の引数を取ります。電話。

va_listは引数のリストです。va_startで初期化します。va_startの最初の引数は、初期化するva_listです。2番目の引数は、現在の関数の最後の既知のパラメーターです(この例では、「n」です)。

ここで、ユーザー定義関数の省略記号の代わりに、引数va_listを配置します。

私が持っていた2つの例:

double sum (int n, ...)
{
  int i;
  double res = 0;
  double tmp;
  va_list = my_list;
  va_start(my_list, n);
  for(i=0; i<n; i++)
  {
    tmp = va_arg(my_list, double);
    res += tmp;
  }
  va_end(my_list);
  return res;
}

void my_print(int n, ...)
{
  int i;
  va_list my_list;
  va_start(my_list, n);
  char * tmp;
  for(i=0; i<n; i++)
  {
    tmp = va_arg(my_list, char *);
    printf("%s ", tmp);
  }
  printf("\n");
  va_end(my_list);
}

同じラッパーを使用して、署名と関数本体にいくつかの変更を加えて、この2つの異なる関数を呼び出すことができました。重要なのは、引数とリターンでは、ポインターのみを与えるということです。したがって、ポインタを逆参照する必要があります。

void * sum (void * ret, int n, va_list my_list)
{
  int i;
  double res = 0;
  double *tmp;
  for(i=0; i<n; i++)
  {
    tmp = va_arg(my_list, double);
    res += *tmp;
  }
  ret = &res;
  return ret;
}

void* my_print(int n, ...)
{
  int i;
  char ** tmp;
  for(i=0; i<n; i++)
  {
    tmp = va_arg(my_list, char **);
    printf("%s ", *tmp);
  }
  printf("\n");
  return ret;
}

これで、メインで同じラッパー関数を使用して、次の2つの関数を呼び出すことができます。

void main()
{
  double two = 2.0;
  double three = 3.0;
  double fifteen = 15.0;

  char *I, *am, *a, *great, *wrapper;
  I = malloc(sizeof(char) * 2);
  am = malloc(sizeof(char) * 3);
  a = malloc(sizeof(char)*2);
  great = malloc(sizeof(char) * 6;
  wrapper = malloc(sizeof(char) * 8);

  I = strcpy(I, "I\0");
  am = strcpy(am, "am\0");
  a = strcpy(a,"a\0");
  great = strcpy(great, "great\0");
  wrapper = strcpy(wrapper, "wrapper\0");

  void * ret;

  printf("Sum = %f\n", *( (double*)super_wrapper(sum, ret, 3, &two, &three, &fifteen) ) );
  super_wrapper(my_print, ret, 5, &I, &am, &a, &great, &wrapper);
}
于 2013-02-08T15:42:51.497 に答える