引用特定的函数参数

时间:2018-07-15 04:59:47

标签: c++ function arguments

好吧,令人困惑的问题。如果我有一个具有多个可选参数的函数或类构造函数(实际上只是一个特殊的函数),是否可以指定一个参数?例如:

float divide ( float a = 1.0, float b = 1.0 ) { return a / b; }

如何在不指定a的情况下指定b

P.S。我知道这个例子有些人为,但是到了重点。

1 个答案:

答案 0 :(得分:1)

C ++中没有内置选项来命名调用中的特定参数(例如在Python中)。

可以使用辅助struct来伪造此类命名参数。示例:

#include <iostream>

struct Denom {
  float x;
  Denom(float x): x(x) { }
};

struct Num {
  float x;
  Num(float x): x(x) { }
};

float divide(float a, float b) { return a / b; }
inline float divide(const Num &num) { return divide(num.x, 1.0f); }
inline float divide(const Denom &denom) { return divide(1.0f, denom.x); }

int main()
{
  // regular call:
  std::cout << "3 / 2: " << divide(3.0f, 2.0f) << '\n';
  // call with numerator only:
  std::cout << "3 / default: " << divide(Num(3.0f)) << '\n';
  // call with denominator only:
  std::cout << "default / 2: " << divide(Denom(2.0f)) << '\n';
  // done
  return 0;
}

输出:

3 / 2: 1.5
3 / default: 3
default / 2: 0.5

Live Demo on coliru


我记得,辅助struct技巧甚至可以扩展为允许链接以及任意顺序的参数。搜寻“ C ++命名参数”,我在SO: C++ named arguments implementation with derived classes的答案之一中找到了另一个示例。示例:

#include <iostream>

struct Args {
  float x, y;
  Args(): x(1.0f), y(1.0f) { }
  Args& num(float x) { this->x = x; return *this; }
  Args& denom(float y) { this->y = y; return *this; }
};

float divide(float a, float b) { return a / b; }
float divide(const Args &args) { return divide(args.x, args.y); }

int main()
{
  // regular call:
  std::cout << "3 / 2: " << divide(3.0f, 2.0f) << '\n';
  // call with numerator only:
  std::cout << "3 / default: " << divide(Args().num(3.0f)) << '\n';
  // call with denominator only:
  std::cout << "default / 2: " << divide(Args().denom(2.0f)) << '\n';
  // args in arbitrary order:
  std::cout << "3 / 2: " << divide(Args().denom(2.0f).num(3.0f)) << '\n';
  // done
  return 0;
}

输出:

3 / 2: 1.5
3 / default: 3
default / 2: 0.5
3 / 2: 1.5

Live Demo on coliru


一次,我看到了gtkmm中的一个简单技巧,我会不时使用它自己–提供一个额外的enum参数来消除歧义。示例:

#include <iostream>

enum ArgInitNum { InitNum };
enum ArgInitDenom { InitDenom };

float divide(float a, float b) { return a / b; }
inline float divide(ArgInitNum, float a) { return divide(a, 1.0f); }
inline float divide(ArgInitDenom, float b) { return divide(1.0f, b); }

int main()
{
  // regular call:
  std::cout << "3 / 2: " << divide(3.0f, 2.0f) << '\n';
  // call with numerator only:
  std::cout << "3 / default: " << divide(InitNum, 3.0f) << '\n';
  // call with denominator only:
  std::cout << "default / 2: " << divide(InitDenom, 2.0f) << '\n';
  // done
  return 0;
}

输出:

3 / 2: 1.5
3 / default: 3
default / 2: 0.5

Live Demo on coliru


注意:

对于简单的函数,我不会使用此技术,在简单函数中,您可以简单地使用不同的函数名。但是,这是消除构造函数歧义的不错选择。