是否有可能以某种方式使函数(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和模板专门化有关,但可能不是.
发布于 2014-01-26 15:40:13
在这里,明智的做法是直接使用三个函数。如果您绝对必须具有以下语法:
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);
}请注意,您不会与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)约束的浮点类型,则在调用之前将参数的值转换为提升类型。这些晋升称为默认参数升级。
发布于 2014-01-26 10:38:36
归根结底是有几个重载,所以最简单的方法是定义:
fillSolid(Brush b)fillGradient(Color c1, Color c2)在这个设计中,您需要在编译时在每个特定调用中知道枚举值,所以没有什么可获得的。
OTOH您可能希望重新设计您的代码,这样您就可以使用不同的实现(如Fill、Gradient1、Gradient2等)来进行实际的抽象,而不是enum,每个实现都有自己的数据集。
后续:这是一个可以使用模板获得的语法示例:
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));枚举数现在是类模板参数,而不是函数参数,因此它在编译时被解析,并且(成员)函数签名能够依赖它。
https://stackoverflow.com/questions/21362308
复制相似问题