为什么默认参数不能依赖于非默认参数?

时间:2016-06-20 09:46:10

标签: c++ c++11

考虑以下构造函数:

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作为参数的副本,否则,调用该函数并将其作为返回值的副本进行初始化。为什么编译器不能理解这一点?

3 个答案:

答案 0 :(得分:9)

C ++标准禁止它。

dcl.fct.default

  每次调用函数时都会计算

9默认参数   没有相应参数的参数。参数不得   在默认参数中显示为可能已评估的表达式。   在默认参数之前声明的函数的参数   范围,可以隐藏命名空间和类成员名称。

     

[例如:

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
     

- 结束示例]

请注意,如果未提供

,则默认参数在呼叫站点替换

Intro.execution (强调我的)

  

11: [注意: 完整表达式 的评估可以包括对子表达式的评估不是词汇的一部分   全表达即可。例如,参与评估的子表达式   默认参数([dcl.fct.default])被认为是创建的   在调用函数的表达式中,不是表达式   定义默认参数。 - 结束说明]

您可以简单地重载构造函数并委托它:

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

脚注:制作单个参数构造函数是一件好事explicit

答案 1 :(得分:2)

另一种方法是使用

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

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

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

答案 2 :(得分:1)

因为默认参数本身必须是完整的,所以如果没有通过调用提供,编译器可以简单地替换它。 (本地)变量dimension尚未创建,您正在尝试使用它,因此也就是错误。然而,这可行:

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

我不确定标准是什么,但是对于编译器实现来说,处理这种极端情况会很棘手。

编辑(完整性),从this answer抓取:

  

每次调用函数时都会计算默认参数。该   函数参数的评估顺序未指定。   因此,默认情况下不应使用函数的参数   参数表达式,即使它们未被评估。