C 11功能参数

C++11 function parameters

本文关键字:参数 功能      更新时间:2023-10-16

是否有可能以某种方式制作功能(C 11),该功能会根据第一个来接受不同的参数吗?可以说,我需要以下行为:

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){};

呼叫示例:

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)){};

只是想知道是否可以。我觉得这可能与enable_if和模板专业化有关,但可能不是...

它归结为具有多个过载,因此最简单的方法是定义:

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

在此设计中,您需要在每个特定呼叫中在编译时间中知道的枚举价值,因此没有太多要获得的。

otoh您可能想重新设计代码,以便与枚举有关Fill的实际抽象,具有不同的实现,例如SolidGradient1Gradient2等,每个实现都有自己的数据集。


随访:这是您可以使用模板获得的语法的一个示例:

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));

现在枚举器是类模板参数,而不是函数参数,因此在编译时解决了它,并且(成员)函数签名能够依赖它。

理智的事情是使用您直接具有的三个函数。如果您绝对必须具有语法:

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));

您可以从两个过载中获得它:

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;
  }
}

,如果您想要一个函数足够严重,可以抛出类型安全以及任何可能调试错误的可能性,则可以使用C风格的varargs:

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);
}

请注意,您不要因C 11§5.2.2/7中详细介绍的va_arg要求。

当没有参数的参数没有参数时,该参数的传递是通过调用va_arg(18.10)来获得参数值的方式传递的。在参数表达式上执行LVALUE-to-rvalue(4.1),阵列到二重奏(4.2)和函数对二次转换(4.3)标准转换。std::nullptr_t类型的参数(可能是CV值)被转换为void*类型(4.10)。在这些转换之后,如果该参数没有算术,枚举,指针,指向成员的指针或类型类型,则该程序的形式不佳。通过具有非平凡复制构造函数的类型(第9条)的潜在评估参数,非平凡的移动构造或没有相应参数的非平凡的驱动器,并由实现定义的语义符合条件支持。如果该参数具有受积分促销(4.5)或受浮点促销的浮点类型的影响(4.6)的积分或枚举类型,则该参数的值将转换为呼叫之前的升级类型。这些促销被称为默认参数促销