2015-04-14 9 views
27

Sono stato sorpreso di scoprire che GCC consente alle funzioni di restituire gli array quando viene utilizzato il tipo di ritorno finale anziché normale. Come probabilmente saprai, gli array non possono essere copiati, quindi è abbastanza limitato, ma lascia che ti mostri un po 'cool example.GCC consente di restituire gli array dalla funzione - bug o funzionalità?

#include <iostream> 
#include <typeinfo> 

using namespace std; 

auto func() -> int [5] 
{ 
    return {4, 56, 78, 4, 0}; 
} 

int main() 
{ 
    cout << func()[2] << endl; 
    cout << typeid(func).name() << endl; 
} 

Si tratta di un bug del compilatore o di qualche nuova funzionalità?

È interessante notare che "typeid" restituisce "FA5_ivE" che è contrassegnato come "int (()) [5]" e ciò significa esattamente ciò che si pensa che una funzione restituisca un array di 5 int.

EDIT: Ho provato delimita la matrice restituita in riferimento rvalue ma senza successo (serve la maggior parte delle forme possibili):

auto &&refArrayTemp{ func() }; 

sembra che questa estensione è piuttosto inutile.

+0

immagino th all'array è un 'const const statico []' uno ... Se questo è il caso, il compilatore si sta comportando correttamente. –

+1

@BasileStarynkevitch non è così; Posso scrivere 'func' prendendo i parametri' int' e sono posizionati nell'array restituito. – ecatmur

risposta

13

Questo era un bug in gcc (fisso as of 2017-07-03), causato da un trattamento incoerente di tipi di ritorno finali.

Prima nota la differenza di messaggio di errore tra due tentativi di dichiarare una funzione che restituisce una funzione:

using Fv = void(); 
Fv f1();    // error: 'f1' declared as function returning a function 
auto f2() -> Fv;  // error: function return type cannot be function 

Il primo errore viene da decl.c, la manipolazione dichiaratori, mentre il secondo è molto più in profondità i meccanismi interni, da tree.c, tentando di creare il tipo di funzione preparatorio alla generazione del codice.

I tipi di ritorno in coda vengono gestiti in decl.c 30 lines below l'errore di cui sopra - troppo tardi per essere rilevato con il codice di errore sopra riportato e non viene gestito separatamente.

Con gli array, analogamente utilizzando un tipo di ritorno trailing ci consente di saltare i controlli in decl.c, con la differenza che function-returning-array è effettivamente valido in termini di rappresentazione interna di gcc.

Si noti che non si può fare molto con esso; gcc non consente di assegnare, di riferimento-bind, carie o passare il risultato di func() a un'altra funzione:

auto a1 = func(); 
// error: invalid use of non-lvalue array 

auto& a2 = func(); 
// error: invalid initialization of non-const reference of type 'int (&)[5]' from an rvalue of type 'int [5]' 

auto&& a3 = func(); 
// error: lvalue required as unary '&' operand 

In effetti, anche il codice viene rifiutata al -Wpedantic:

warning: ISO C++ forbids subscripting non-lvalue array 

Infine, sfruttando un insetto simile (qualificatori vengono rimossi dai scalari prima dell'uso di trascinamento-ritorno-tipi) possiamo creare una funzione di tipo int const volatile():

int const volatile g1();   // warning: type qualifiers ignored on function return type 
auto g2() -> int const volatile; // OK!! 
+0

Si prega di non risolvere questo problema. Piuttosto, consentire le operazioni dell'array. Sarebbe molto carino se lo fai. Come l'array che copia per valore e che si lega ai riferimenti 'rvalue'. Nessuna compatibilità andrà persa e non penso che sarà molto difficile da fare, ma sarà facile per le nostre vite. – AnArrayOfFunctions

+6

@FISOCPP già possibile. 'std :: array' è molto meglio di un array in stile C integrato. – edmz

+0

Ma perché non consentire entrambi? Gli array Bult-in sembrano molto più interessanti. – AnArrayOfFunctions

8

Ultima bozza, [dcl.array]/p10:

funzioni non devono avere un tipo di ritorno di tipo array o funzione, anche se possono avere un tipo di ritorno puntatore tipo o riferimento a tale cose. Non ci devono essere matrici di funzioni, sebbene possano essere presenti le matrici di puntatori alle funzioni.

Questa potrebbe essere un'estensione GCC non standard. It doesn't compile in the trunk version of clang. Tuttavia, questo potrebbe anche essere un bug poiché ha un comportamento incoerente con uno non-trailing return type.

+0

Quindi, cosa? Voglio dire, sapevamo che non era legale e potrebbe essere un bug o una sorta di estensione. – edmz

+0

@black A cosa ti riferisci? – 0x499602D2

Problemi correlati