2011-01-31 14 views
8

Questa domanda, ovviamente, per scontato che noi non vogliamo utilizzare i modelli di questo tipo (per qualsiasi motivo).Il C++ 0x consente decltype() nella firma della funzione?

class Product 
{ 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 


private: 

    float mPrice ; // type might later be changed to more acurate floating point abstraction 
    std::string mLabel; // type might later be changed by a special localization-oriented string 
}; 

La domanda è: sono 1. e 2. ammessi e possibile (o addirittura specificamente definito) in C++ 0x?

risposta

7

Tutto quello che dovete fare è dichiarare mPrice e mLabelprima di utilizzare decltype:

class Product 
{ 
private: 
    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 
}; 

Questo compila bene sotto g ++ 4.4 con -std = C++ 0x.

Modifica Il punto è che il compilatore deve essere in grado di analizzare le dichiarazioni di funzione al primo passaggio. Il corpo di una funzione membro può essere compilato dopo che le dichiarazioni dei membri sono state analizzate, ma le dichiarazioni dei membri devono essere immediatamente comprensibili - altrimenti, da dove viene il povero compilatore?

Quindi il tipo di argomento di ogni funzione membro deve essere noto non appena viene rilevato.

+0

Fantastico! È un comportamento standard o solo un comportamento di implementazione di gcc? – Klaim

+0

Per quanto ne so, questo è un comportamento standard. – TonyK

+0

@Klaim Lo standard dice "Un tipo di ritorno specificato più tardi è più utile per un tipo che sarebbe più complicato specificare prima dell'id dichiaratore" che sembra indicare che inserire il decltype prima che la funzione sia valida e il valore di ritorno finale è opzionale per i casi in cui è più semplice (o lamdas dove necessario) – MerickOWA

8

Sì, ma con una diversa sintassi:

auto price() -> decltype(mPrice) { return mPrice; } 
auto price() -> decltype(mPrice) { return mPrice; } 

più generale:

auto function(...) -> decltype(EXPRESSION) ... 

function tipo di ritorno sarà il tipo di EXPRESSION


EDIT

sul caso 1 non sono sicuro. Non credo sia valido, dal momento che non penso che mPrice sia un'espressione valida in tale contesto: stai usando un membro non statico della funzione (Product::mPrime) senza un oggetto.

La mia ipotesi è anche che se mPrime fosse un membro statico, funzionerebbe.

+0

Sei sicuro, sto ricevendo un errore di compilazione con g ++ perché le variabili non sono in ambito (il che ha senso dato che sono variabili di istanza). – Motti

+0

Non si risponde per il caso 1.. – Klaim

+0

@Klaim: aggiornato la mia risposta – peoro

1

AFAIK questo è non legale poiché le variabili di istanza non sono nell'ambito dei punti in cui le si utilizzano.

considerare che cosa accadrebbe se si ha le seguenti variabili dichiarate prima della classe:

int mPrice; 
char mLabel; 
class Product 
{ /*...*/ }; 

Nella funzione decleration mPrice legherebbe alla variabile globale piuttosto che il membro di istanza.

Sia g ++ 4.5 che VS10 rifiutano di compilare il codice poiché mPrice e mLabel sono fuori portata.

Tuttavia, questo sembra essere incoerente con i parametri di default.

int mPrice = 3; 
class Product 
{ // ... 
    int foo(int i = mPrice) { return i; } 
}; 

Product p(5.3, "hi"); 
std::cout << p.foo(); 

Questo mi dà un errore di compilazione:

invalid use of non-static data member 'Product::mPrice'

+0

Beh, non lo so, perché decltype() accetta espressioni, quindi il punto è che l'espressione non viene valutata in questo caso, ma è nel tuo esempio. Quindi quello che sto chiedendo è nel caso di decltype(), sarà in grado di usare l'espressione o è esplicitamente proibito? – Klaim

2

VC++ 2010 compila questo w/o errori:

 

class Product 
{ 
private: 

    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) 
     : mPrice(price_), mLabel(label_){} 

    auto price(decltype(mPrice)* p=NULL) const -> decltype(mPrice) {return mPrice;} 

    auto label(decltype(mPrice)* m=NULL) const -> decltype(mLabel) {return mLabel;} 

}; 

ma se rimuovere i parametri predefiniti fittizi dalle dichiarazioni metodi, l'errore si verifica di nuovo. decltype in return type funziona solo se appare anche in qualche parametro funzione (???)

(Mi spiace, capisco che dovrebbe essere un commento, ma sembra interessante e non è conveniente inserire il codice nei commenti)

+0

Questo compila bene sotto g ++ 4.4.0 con -std = C++ 0x, anche dopo aver rimosso i parametri predefiniti dummy. Vedi http://ideone.com/jGrak per prova. – TonyK

+0

@TonyK: Non avevo quasi alcun dubbio che gcc dovrebbe compilare questo codice se compila il codice che presenti nella risposta. Gli errori sono probabilmente specifici msvC++, ma molto strano, comunque. – user396672

+0

È interessante notare che non sembra importare quale sia il parametro, basta che ce ne sia uno. Il parametro potrebbe essere solo "prezzo automatico (int = 0)" e funziona ancora. – MerickOWA

Problemi correlati