Можно ли получить функцию (n-1) -аргумента из функции с n-аргументами, установив один аргумент в фиксированное значение? - PullRequest
1 голос
/ 21 октября 2011

Мне было интересно, можно ли в C ++ получить функцию, принимающую (n-1) аргументов, из функции, принимающей n аргументов, установив для n-го аргумента значение, равное некоторому значению (которое определяется во время выполнения)?

Например, я хотел бы сделать что-то вроде следующего:

float foo(float a, float b, float c){
  // do some stuff
}

float bar(float x, float y, float f(float q, float r)){
  return f(x,y);
}

int main(){
  double (*function)(float, float);
  float some_value;
  // somehow determine some_value, e.g. read from stdin.
  // Now I would like to set function something along the lines of:
  function = foo( . , . , some_value)
  return bar(123, 456, function);
}

Концептуально, foo - это семейство функций, индексированных c, то есть семейство функций foo_c (float a, float b) (читать «foo_c» как «foo subscript c» здесь), и я хочу передать foo_c соответственно указатель на него в качестве аргумента bar.

Возможно ли это вообще в C ++?Насколько я знаю, это невозможно с указателями функций, как указано выше.Есть ли другой способ сделать что-то подобное?

Я кратко подумал о том, чтобы сделать foo шаблоном функции, но это не сработает, так как я хочу установить его третий аргумент во время выполнения.

Очевидное решение, конечно, состоит в том, чтобы изменить bar так, чтобы он принимал тип float f(float q, float r, float t) в качестве третьего аргумента, но это сделает код намного менее пригодным для повторного использования (и выглядит менее элегантно).Я также хочу передать другие функции в bar, некоторые из которых будут принимать только два аргумента, более трех, или аргументы разных типов, которые мне как-то нужно установить на фиксированное значение, прежде чем передавать их в bar.

Я не совсем смог выяснить, смогу ли я сделать bar шаблонной функцией в этом случае по линиям template <typename T, typename S> float bar(float x, float y, T f(float a, float b, S param), S parameters), а затем вызвать ее, используя что-то вроде bar <double *(float, float, float), float> (123, 456, function, parameters).Будет ли что-нибудь в этом духе работать вообще?

Ответы [ 2 ]

4 голосов
/ 21 октября 2011

Вы не можете сделать это с помощью таких указателей на функции, но вы можете сделать это с помощью объектов, подобных функциям.C ++ 11 дает вам std::bind и std::function (а также лямбды, но я не знаю достаточно о них, чтобы привести пример);в C ++ 03 boost::bind и boost::function очень похожи.

float foo(float a, float b, float c){
  // do some stuff
}

float bar(float x, float y, function<float(float, float)> f){
  return f(x,y);
}

int main(){
  float some_value;
  // somehow determine some_value, e.g. read from stdin.

  return bar(123, 456, bind(foo,_1,_2,some_value));
}
4 голосов
/ 21 октября 2011

Вы не можете сделать это с помощью указателей на функции, однако это можно сделать с помощью функциональных объектов.Я рекомендую вам посмотреть Boost.Bind , если вы используете C ++ 03.Если вы используете C ++ 11, std::bind является частью стандарта и работает так же.В C ++ 11 также представлены встроенные лямбды, которые делают то, что вы пытаетесь.

Для хранения результата bind или лямбды вы можете использовать Boost.Function в C ++03 или std::function в C ++ 11.

В этом примере вы можете сделать это в C ++ 03.

float foo(float a, float b, float c){
  // do some stuff
}

float bar(float x, float y, boost::function<float(float,float)> f){
   return f(x,y);
}

int main(){
  boost::function<float(float,float)> func;
  float some_value;
  // somehow determine some_value, e.g. read from stdin.
  // Now I would like to set function something along the lines of:
  func= boost::bind(foo, _1, _2, some_value);
  return bar(123, 456, func);
}

В C ++ 11 вы можете использовать стандартизированные версии bind и function или лямбда-функцию:

float foo(float a, float b, float c){
  // do some stuff
}

float bar(float x, float y, std::function<float(float,float)> f){
   return f(x,y);
}

int main(){
  std::function<float(float,float)> func;
  float some_value;
  // somehow determine some_value, e.g. read from stdin.
  // Now I would like to set function something along the lines of:
  func= [some_value](float x, float y) { return foo(x,y,some_value); };
  return bar(123, 456, func);
}
...