2013-12-09 13 views
25

non capisco il motivo per cui questo codice venga compilato senza errori:Restituire un vuoto?

#include <iostream> 

template <class T> 
struct Test 
{ 
    static constexpr T f() {return T();} 
}; 

int main() 
{ 
    Test<void> test; 
    test.f(); // Why not an error? 
    return 0; 
} 

E 'ok secondo lo standard, o si tratta di una tolleranza compilatore?

+0

Beh, so che stai permesso di avere, per esempio, 'foo void() {} bar void() {return foo();}'. Non sono sicuro di questo. – chris

+1

Qual è la tua domanda su, in particolare? Informazioni sulla restituzione di 'void' (che, BTW, è sempre stato legale in C++)? O sulla combinazione 'constexpr void'? – AnT

+3

Forse dovresti spiegare cosa pensi che dovrebbe essere l'errore? –

risposta

24

Questo sembra valida dal draft C++11 standard, se guardiamo alla sezione 5.2.3conversione di tipo esplicita (notazione funzionale) paragrafo dice (sottolineatura mia):

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of type T; no initialization is done for the void() case.[...]

la formulazione è abbastanza simile pre C++11 pure.

Questo va bene in un constexpr anche se la sezione 7.1.5 comma 3 dice:

The definition of a constexpr function shall satisfy the following constraints:

e comprende questo proiettile:

its return type shall be a literal type;

e vuoto non è un letterale in C++ 11 come da sezione 3.9 comma , ma Se poi guardiamo al paragrafo dà un'eccezione che si inserisce questo caso, si dice:

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member function it will still be const as described below. —end note ] If no specialization of the template would yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.

Come Casey noted nel C++14 draft standardvuoto è un letterale, questa è la sezione 3.9Tipi paragrafo dice:

A type is a literal type if it is:

e comprende:

— void; or

6

Vedere la risposta di @Shafik Yaghmour per le informazioni complete.

il seguente paragrafo proibisce questo per i non-modelli (7.1.5 (3)):

The definition of a constexpr function shall satisfy the following constraints:

  • [...]

  • its return type shall be a literal type or a reference to literal type

Elaborare, un tipo letterale è definito in 3,9 (10) come un tipo scalare o una composizione di oggetti di tipo letterale in una matrice o una struttura. void non è un tipo scalare di 3.9 (9).

+1

* tipo letterale * è definito in 3.9/10; 'void' è * non * un tipo letterale in C++ 11. In C++ 14 (N3797) tuttavia, 'void' * è * incluso nei tipi letterali. Quindi il codice dell'OP sarà conforme a C++ 14. – Casey

+2

@Casey Inoltre penso che 7.1.5 il paragrafo 6 lo consenta in C++ 11 –

+1

@ShafikYaghmour Ahh, sono d'accordo. Interessante: questo codice è specializzato in una funzione membro non -constexpr' ma 'const' in C++ 11, o una funzione membro' constexpr' e non-'const' in C++ 14! – Casey

1

La funzione restituisce il valore di void(), non si torna da una funzione di annullamento di per sé. Si sta restituendo un valore NULL. Quello che stai facendo equivale a questo:

void f() { return void(); } 

Questo restituisce un valore nullo, l'unico valore void. non puoi restituire nient'altro da una funzione di vuoto perché sarà di un tipo diverso.

+0

Sono abbastanza sicuro che ciò sia permesso in C++ dalla 5.2.3 (2), sebbene IANALL. – filmor

+0

È consentito dal compilatore, ma non è molto utile in quanto non ha alcun valore. – user3084096

+2

Non è questo il punto quando si parla di uno standard linguistico. – filmor