首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11函数参数

C++11函数参数
EN

Stack Overflow用户
提问于 2014-01-26 10:30:59
回答 2查看 236关注 0票数 0

是否有可能以某种方式使函数(C++11)根据第一个参数接受不同的参数?让我们说,我需要以下行为:

代码语言:javascript
复制
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){};

打电话给示例:

代码语言:javascript
复制
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和模板专门化有关,但可能不是.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-26 15:40:13

在这里,明智的做法是直接使用三个函数。如果您绝对必须具有以下语法:

代码语言:javascript
复制
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));

你可以从两个过载中得到它:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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);
}

请注意,您不会与va_arg要求发生冲突,如C++11第5.2.2/7节所详述的那样:

当给定参数没有参数时,参数的传递方式使接收函数能够通过调用va_arg (18.10)获得参数的值。对参数表达式执行从lvalue到rvalue (4.1)、数组到指针(4.2)和函数到指针(4.3)的标准转换.具有(可能是cv限定的)类型std::nullptr_t的参数被转换为void* (4.10)类型。这些转换之后,如果参数没有算术、枚举、指针、指向成员的指针或类类型,则程序的格式不正确。传递具有非平凡复制构造函数、非平凡移动构造函数或非平凡析构函数且没有相应参数的类类型的潜在评估参数(第9条),有条件地支持实现定义的语义。如果参数具有受积分提升(4.5)约束的整数或枚举类型,或受浮点提升(4.6)约束的浮点类型,则在调用之前将参数的值转换为提升类型。这些晋升称为默认参数升级。

票数 0
EN

Stack Overflow用户

发布于 2014-01-26 10:38:36

归根结底是有几个重载,所以最简单的方法是定义:

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

在这个设计中,您需要在编译时在每个特定调用中知道枚举值,所以没有什么可获得的。

OTOH您可能希望重新设计您的代码,这样您就可以使用不同的实现(如FillGradient1Gradient2等)来进行实际的抽象,而不是enum,每个实现都有自己的数据集。

后续:这是一个可以使用模板获得的语法示例:

代码语言:javascript
复制
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));

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21362308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档