2016-06-20 19 views
6

は、次のコンストラクタを考えます。なぜデフォルト引数はデフォルト以外の引数に依存できないのですか? <code>unitaryVector(d)</code>をd次元のランダム<code>std::vector</code>を返す関数である</p> <pre><code>class MyClass { MyClass(unsigned int dimension, std::vector vector=unitaryVector(dimension)); }; </code></pre><p>:

これは、次のコンパイラエラーを与える:

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

なぜこのイディオムはC++ 11で有効ではありませんか?それはかなり明白です:vector引数が提供されている場合は、引数のコピーとしてvectorを初期化します。それ以外の場合は、関数を呼び出して戻り値のコピーとして初期化します。コンパイラがこれを理解できないのはなぜですか?

+0

あなたの機能要求は、非常に合理的なものと思われますが、それは標準ですか?そうでない場合、コンパイラ作成者はそれを実装する義務がありません。 – pyon

+1

可能な複製http://stackoverflow.com/questions/1880866/cc-default-argument-set-as-a-previous-argument –

+0

std :: optional <>をデフォルトの値emptyの代わりに使用することがあります明示的なデフォルト値これには、デフォルト値があなたの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

1つの選択肢は

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

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

を使用することである単一の引数のコンストラクタを作るために(これはもちろん、dimensionvectorをクラスに保存する場合)。

関連する問題

 関連する問題