2016-06-20 7 views
6

sich das folgende Konstruktor:Warum kann das Standardargument nicht von einem Standardargument abhängen?

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

wo unitaryVector(d) ist eine Funktion, die eine zufällige std::vector in D Dimensionen zurückkehrt.

Dies gibt den folgenden Compiler-Fehler:

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

Warum ist das nicht Idiom gültig in C++ 11? Es scheint ziemlich offensichtlich zu sein: Wenn das Argument vector bereitgestellt wird, init vector als eine Kopie des Arguments, andernfalls rufen Sie die Funktion auf und init es als eine Kopie des Rückgabewerts. Warum kann ein Compiler das nicht verstehen?

+0

Ihre Feature-Anfrage scheint eine sehr vernünftige Sache zu sein, aber, ist es im Standard? Wenn nicht, sind Compiler-Autoren nicht verpflichtet, es zu implementieren. – pyon

+1

möglich Duplikat von http://StackOverflow.com/Questions/1880866/cc-default-argument-set-as-a-previous-argument –

+0

Sie könnten ein Std :: Optional <> mit einem Standardwert von leer anstelle von verwenden ein expliziter Standardwert Dies hat den Vorteil, dass der Standardwert nicht Teil Ihres ABI ist und das Patchen einfacher wird. – lorro

Antwort

9

Der C++ Standard verbietet.

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 ]

Beachten Sie, dass Standardargumente sind an der Aufrufstelle ersetzt, wenn nicht

bereitgestellt

Intro.execution(Hervorhebung von mir)

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 ]


Sie können einfach den Konstruktor überlasten und delegieren:

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

Fußnote: Es ist eine gute Sache

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

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

verwenden Argument Konstrukteuren explicit

1

Da das Standardargument in sich abgeschlossen sein muss, damit der Compiler es einfach ersetzen kann, wenn es nicht durch Aufruf bereitgestellt wird. Die (lokale) Variable dimension ist noch nicht erstellt und Sie versuchen, sie zu verwenden, und daher der Fehler. Dies funktionieren würde, aber:

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

Ich bin nicht sicher, was Standard sagt, aber für Compiler-Implementierung wäre heikel solche Ecke Fälle zu behandeln.

EDIT (auf Vollständigkeit), nahm von 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

Eine Alternative ist, zu machen (Dies natürlich, wenn Sie dimension und vector in der Klasse speichern möchten).

Verwandte Themen