2016-06-20 187 views
6

考虑以下构造:为什么不能默认参数取决于非默认参数?

class MyClass { 
    MyClass(unsigned int dimension, std::vector vector=unitaryVector(dimension)); 
}; 

其中unitaryVector(d)是返回d维随机std::vector的功能。

这提供了以下编译器错误:

error: default argument references parameter 'dimension' 
    MyClass(unsigned int dimension, std::vector vector=unitaryVector(dimension)); 

为什么没有这个成语在C++ 11有效吗?这似乎很明显:如果提供了vector参数,则将init vector作为参数的副本,否则,调用该函数并将它初始化为返回值的副本。为什么编译器不能理解这一点?

+0

你的功能需求似乎是一个非常合理的事情,但是,它是在标准?如果不是,编译器作者没有义务实施它。 – pyon

+1

http://stackoverflow.com/questions/1880866/cc-default-argument-set-as-a-previous-argument –

+0

可能的重复您可能会使用std :: optional <>,其默认值为空,而不是一个明确的默认值。这具有以下优点:默认值不会成为ABI的一部分,因此修补将更加容易。 – lorro

回答

9

C++标准禁止它。

dcl.fct.default

9 default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.

[ Example:

int a; 
int f(int a, int b = a);   // error: parameter a 
            // used as default argument 
typedef int I; 
int g(float I, int b = I(2));  // error: parameter I found 
int h(int a, int b = sizeof(a)); // OK, unevaluated operand 

— end example ]

注意,默认参数是在调用点更换如果没有提供

Intro.execution(重点煤矿)

11:[ Note: The evaluation of a full-expression can include the evaluation of subexpressions that are not lexically part of the full-expression. For example, subexpressions involved in evaluating default arguments ([dcl.fct.default]) are considered to be created in the expression that calls the function, not the expression that defines the default argument. — end note ]


你可以简单地重载构造函数,委托它:

class MyClass { 
    explicit MyClass(unsigned int dimension) 
     : MyClass(dimension, unitaryVector(dimension)) //delegation 
    { } 
    MyClass(unsigned int dimension, std::vector vector); 
}; 

脚注:它是一件好事,使一个参数的构造函数explicit

1

由于默认参数本身必须完整,因此如果不是由调用提供的,编译器可以简单地替换它。 (本地)变量dimension尚未创建,您正在尝试使用它,因此出现错误。这会工作,但是:

int _def_dim=10; 
class MyClass { 
    MyClass(unsigned int dimension, std::vector vector=unitaryVector(_def_dim)); 
}; 

我不知道是什么标准说,但对于编译器的实现将是棘手的处理这种极端情况。

EDIT(出于完整性),从this answer抓起:

Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in default argument expressions, even if they are not evaluated.

1

一种替代方法是使用

class MyClass { 
    MyClass(unsigned int dimension, std::vector const& vector) : 
      dimension(dimension), vector(vector) {} 

    MyClass(unsigned int dimension) : 
      MyClass(dimension, unitaryVector(dimension)) {} 
}; 

(这当然当你想在课堂上储存dimensionvector)。