2014-09-04 18 views
7

sguardo al codice:Perché è possibile utilizzare il costruttore predefinito privato in decltype()?

#include <iostream> 
#include <utility> 

class test 
{ 
private: 
    test() { } 
public: 
    test foo() { return *this; } 

    static const char *name() { return "test"; } 
}; 

int main() 
{ 
    std::cout << decltype(test().foo())::name() << std::endl;    // 1 
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2 
} 

mi aspettavo // 1 linea non può essere compilato in quanto il costruttore di default di test è privato.

However, it works well. L'ho testato sul mio g ++ 4.8.3 con -Wall -Wextra -Werror -pedantic in incredulità, ma funziona bene senza errori o avvisi.

(In aggiunta, sembra funzionare bene in GCC 4.9.1 pure.)

Da this page, credo che possiamo usare costruttore di default privata se l'espressione è non valutata. Quindi, ho provato quanto segue per controllarlo.

#include <iostream> 
#include <utility> 

class test 
{ 
private: 
    test(int) { } 
public: 
    test foo() { return *this; } 

    static const char *name() { return "test"; } 
}; 

int main() 
{ 
    std::cout << decltype(test().foo())::name() << std::endl;    // 1 
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2 
} 

(live example)

Come previsto, non è stato compilato.

Ma .... perché ?? Com'è possibile? Possiamo utilizzare i membri privati ​​ con espressioni non valutate? O esiste una regola speciale per i costruttori predefiniti? Potresti spiegarmi perché?

+0

Non si compila in clang. –

+0

@ T.C. Oh veramente? allora potrebbe essere solo l'errore di GCC .. – ikh

+1

Um, C++ 98 non ha 'decltype'. O 'declval'. Certo che non si compila. –

risposta

11

Non deve essere compilato. C++ 11 [class.temporary] ha questo da dire circa la creazione di un oggetto temporaneo:

12,2/1 Anche quando la creazione dell'oggetto temporanea è non valutate o comunque evitati, tutte le restrizioni semantiche deve essere rispettato come se l'oggetto temporaneo fosse stato creato e successivamente distrutto. [Nota: anche se non vi è alcuna chiamata al distruttore o copia/sposta costruttore, tutte le restrizioni semantiche , come l'accessibilità e se la funzione viene eliminata, devono essere soddisfatte. Tuttavia, nel caso speciale di una chiamata di funzione utilizzata come operando di uno specificatore decltype , non viene introdotto alcun temporaneo, pertanto quanto sopra non si applica al valore di predizione di tale chiamata di funzione. - nota end]

Così, anche quando non valutata, si sta ancora limitato dalla accessibilità delle eventuali funzioni (tra cui costruttori) necessari per creare e distruggere la temporanea. La frase finale della nota chiarisce che una funzione come declval può essere utilizzata per evitare questo ostacolo.

+1

Grazie . +1 per * la frase finale *. (oh, vedo che non posso accettare una risposta in un minuto> o <) – ikh

+0

Quindi deve essere il bug di gcc; dovrei segnalarlo? > O < – ikh

Problemi correlati