2016-06-20 5 views
6

consideri il seguente costruttore:perché l'argomento predefinito non può dipendere dall'argomento non predefinito?

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

dove unitaryVector(d) è una funzione che restituisce un casuale std::vector in d dimensioni.

Questo dà il seguente errore del compilatore:

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

Perché non è questo idioma valida in C++ 11? Sembra essere abbastanza ovvio: se viene fornito l'argomento vector, init vector come una copia dell'argomento, altrimenti chiama la funzione e la inizia come una copia del valore restituito. Perché un compilatore non può capire questo?

+0

La richiesta di funzionalità sembra una cosa molto ragionevole da volere, ma, è nello standard? In caso contrario, gli autori di compilatori non sono obbligati a implementarlo. – pyon

+1

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

+0

Si potrebbe usare uno std :: facoltativo <> con un valore predefinito di vuoto invece di un valore predefinito esplicito. Questo ha il vantaggio che il valore predefinito non farà parte del tuo ABI e quindi l'applicazione delle patch sarà più semplice. – lorro

risposta

9

Lo standard C++ lo proibisce.

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 ]

Nota che gli argomenti di default sono sostituito presso il sito chiamata se non previsto

Intro.execution(sottolineatura mia)

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 ]


Si può semplicemente sovraccaricare il costruttore e delegarla:

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

Nota: E 'una buona cosa per rendere costruttori di argomenti singoli explicit

1

Poiché l'argomento predefinito deve essere completo in sé, in modo che il compilatore possa semplicemente sostituirlo se non fornito dalla chiamata. La variabile (locale) dimension non è stata ancora creata e si sta tentando di utilizzarla e quindi l'errore. Questo dovrebbe funzionare, però:

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

Non sono sicuro di quello che dice standard, ma per l'attuazione del compilatore è sarebbe difficile da gestire tali casi d'angolo.

EDIT (per completezza), afferrato da 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

Un'alternativa è quella di utilizzare

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

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

(questo ovviamente quando si desidera memorizzare dimension e vector nella classe).

Problemi correlati