简体   繁体   English

C ++ 11函数参数

[英]C++11 function parameters

Is it possible to somehow make functions (C++11) which will accept different parameters depending on the first one? 是否有可能以某种方式使函数(C ++ 11)接受不同的参数取决于第一个? Lets say, I need the following behavior: 可以说,我需要以下行为:

enum TypeFill{Solid, Gradient1, Gradient2};

void fill(const TypeFill t,  Type1 param1 = NULL, Type2 param2 = NULL){
  if (t == Solid){
       fillSolid(param1);
  } else if (t == Gradient1){
       fillGradient1(param1, param2);
  } else if (t == Gradient2){
       fillGradient2(param1, param2);
  }
}

private:
fillSolid(Brush b){};                
fillGradient1(Color c1, Color c2){};
fillGradient2(Color c1, Color c2){};

Call example: 电话示例:

fill(Solid, Brush(1.0, 0.0, 0.0)){};                
fill(Gradient1, Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0)){};
fill(Gradient2, Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0)){};

Just wonder if this possible. 只是想知道这是否可能。 I feel that may be something possible to do with enable_if and template specializations, but may be not... 我觉得这可能与enable_if和模板特化有关,但可能不是......

It boils down to having several overloads, so the simplest way would be to define: 它归结为有几个重载,所以最简单的方法是定义:

  • fillSolid(Brush b)
  • fillGradient(Color c1, Color c2)

In this design you'd need the enum value to be known at compile time anyway in each particular call, so there's not much to gain. 在这个设计中,你需要在每个特定的调用中在编译时知道枚举值,所以没有太大的收获。

OTOH you'd probably want to redesign your code so that instead of an enum you'd have an actual abstraction for Fill with different implementations like Solid , Gradient1 , Gradient2 , etc, each with its own data set. OTOH你可能想重新设计你的代码,这样你就可以使用SolidGradient1Gradient2等不同的实现来实现Fill的实际抽象,而不是枚举,每个实现都有自己的数据集。


Follow-up: This is an example of a syntax that you COULD get with templates: 后续行动:这是您可以通过模板获得的语法示例:

fill<Solid>::call(Brush(1.0, 0.0, 0.0));               
fill<Gradient1>::call(Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0));
fill<Gradient2>::call(Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0));

The enumerator now is a class template parameter, not a function argument, so it's resolved at compile-time and the (member) function signature is able to depend on it. 枚举器现在是一个类模板参数,而不是函数参数,因此它在编译时解析,(成员)函数签名能够依赖它。

The sane thing here would be to use the three functions you have directly. 这里理智的是使用你直接拥有的三个功能。 If you absolutely must have the syntax: 如果你绝对必须有语法:

fill(Solid, Brush(1.0, 0.0, 0.0));
fill(Gradient1, Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0));
fill(Gradient2, Color(1.0, 0.0, 0.0), Color(1.0, 1.0, 0.0));

You can get it from two overloads: 你可以从两个重载中得到它:

void fill(TypeFill t, Brush b) {
    assert(t == Solid);
    fillSolid(b);
}

void fill(TypeFill t, Color c1,  Color c2) {
  switch(t) {
  case Gradient1:
    fillGradient1(c1, c2);
    break;
  case Gradient2:
    fillGradient2(c1, c2);
    break;
  default:
    assert(false);
    break;
  }
}

and if you want a single function badly enough to throw out type-safety along with any possibility of debugging errors, you can use C-style varargs: 如果你想要一个单独的功能足以抛出类型安全以及任何调试错误的可能性,你可以使用C风格的变量:

void fill(TypeFill t, ...) {
  va_list ap;
  va_start(ap, t);
  switch(t) {
  case Gradient1:
    fillGradient1(va_arg(ap, Color), va_arg(ap, Color));
    break;
  case Gradient2:
    fillGradient2(va_arg(ap, Color), va_arg(ap, Color));
    break;
  case Solid:
    fillSolid(va_arg(ap, Brush));
    break;
  default:
    assert(false);
    break;
  }
  va_end(ap);
}

Be careful that you do not fall afoul of the va_arg requirements as detailed in C++11 §5.2.2/7: 请注意,不要像C ++11§5.2.2/ 7中详述的那样违反va_arg要求:

When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10). 当给定参数没有参数时,参数的传递方式使得接收函数可以通过调用va_arg (18.10)来获取参数的值。 The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. 在参数表达式上执行左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)标准转换。 An argument that has (possibly cv-qualified) type std::nullptr_t is converted to type void* (4.10). 具有(可能是cv-qualified)类型std::nullptr_t将转换为void* (4.10)类型。 After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed. 在这些转换之后,如果参数没有算术,枚举,指针,成员指针或类类型,则程序格式错误。 Passing a potentially-evaluated argument of class type (Clause 9) having a nontrivial copy constructor, a non-trivial move contructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics. 传递具有非平凡复制构造函数,非平凡移动构造函数或非平凡析构函数的类类型(第9章)的可能已评估的参数,没有相应的参数,通过实现定义的语义有条件地支持。 If the argument has integral or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call. 如果参数具有由积分促销(4.5)或浮点促销(4.6)限制的浮点类型的积分或枚举类型,则参数的值将在调用之前转换为提升类型。 These promotions are referred to as the default argument promotions . 这些促销被称为默认参数促销

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM