2010-02-04 14 views
6

Ultimamente ho incontrato la seguente costruzione nel codice:Qual è il punto di "typedef sometype sometype"?

typedef sometype sometype; 

Attenzione di paga prego che "sometype" sta per assolutamente lo stesso tipo senza aggiunte come "struct", ecc

Mi chiedo a cosa può essere utile?

UPD: funziona solo per i tipi definiti dall'utente.

UPD2: Il codice reale era in un contesto modello come questo:

template <class T> 
struct E 
{ 
    typedef T T; 
    ... 
} 
+6

Sei sicuro di non aver detto: 'typedef struct sometype sometype;'? –

+2

quindi un esempio concreto sarebbe 'typedef char char'? – SiegeX

+0

Mi sono chiesto il codice di esempio, non credevo potesse essere compilato. Provato. Può: 'struct A {int x; }; int main() {typedef A A; Aa; ritorno 0; } ' – Notinlist

risposta

7

Come rendere i parametri di Template visibili alle entità esterne?

template <class Foo> 
struct Bar 
{ 
    typedef Foo Foo; 
}; 

int main() 
{ 
    Bar<int>::Foo foo = 4; 
} 

Nota: questo non è attualmente consentito in C++ standard, ma è specifico per MSVC. Vedi i commenti.

+4

Allora perché non eliminarlo? –

+0

Abbastanza sicuro che funzioni in alcuni compilatori, quindi se l'OP ha visto questo codice in giro, questo potrebbe essere il motivo, quindi è ancora una risposta valida alla sua domanda. – jalf

+3

@Niel: Perché se lo elimino, qualche altro ragazzo intelligente penserà alla stessa cosa e la pubblicherà di nuovo. A volte vale la pena sapere quale sia la risposta sbagliata. –

6

In C++, si può mettere un typedef in uno spazio dei nomi o di classe, e quindi fare riferimento ad esso rispetto a quella dello spazio dei nomi o classe, che può essere utile se il tipo reale potrebbe cambiare in futuro.

ad es.

class IntHolder 
{ 
    public: 
     typedef int int; 
     IntHolder::int i; 
}; 
... 
IntHolder foo; 
IntHolder::int i = foo.i; 

(NB: non ho controllato che è abbastanza la sintassi giusta - ma spero che si ottiene l'idea)

Se ad un certo punto futuro si vuole realmente tenere long in IntHolder avete solo bisogno di cambiare il codice IntHolder.

Ora, normalmente si denomina il tipo in modo diverso, ma forse si può fare come sopra?

+0

Onorario +1 per uno scenario di uso decente. Posso vedere questo facilmente accadendo per i tipi meno built-in di 'int'. –

+0

Non sembra compilare più di tutte le altre risposte che lo suggeriscono (con GCC e Comeau). - Se si suppone che la classe abbia solo un typedef, basta usare 'typedef X type;', così le persone non dovrebbero indovinare ogni volta. Voglio dire, "IntHolder :: int" risulterebbe essere "long"? Perché chiamarlo ** int ** allora e non 'IntHolder :: type'? – UncleBens

+0

Non l'ho provato - e sono contento di non averlo fatto perché avrei colpito gcc rifiutandolo - mentre il compilatore dell'OP (VS) è riuscito a compilare la versione del template. –

6

Ho una teoria. Potrebbe essere il risultato di alcuni refactoring. Ad esempio un tipo di modello non diventa un modello.

typedef SomeCleverTemplate<Rocket> SuperThing; 

Poi hanno cancellato il modello, allucinante non ci fosse altro uso di esso nel codice, e solo per essere sicuri che ogni sostituiti SomeCleverTemplate<Rocket>-SuperThing.

typedef SuperThing SuperThing; 

Ha senso nel contesto reale?

+0

+1 onorario per "contesto reale di troppa automazione". Spiacente, non è un vero +1, sono fuori per le prossime 12 ore. –

+0

E perché non funziona senza un typedef? –

+0

Lo farebbe. Penso che tu possa cancellare quella linea dal codice. – Notinlist

7

Dato le ulteriori informazioni sui modelli, ora possiamo rispondere.

Il caso d'uso è quando si desidera specializzarsi sul tipo di modello. Un esempio tipico è il seguente:

template <typename T> 
struct nonconst { 
    typedef T t; 
}; 

template <typename T> 
struct nonconst<T const> { 
    typedef T t; 
}; 

Questo permette in modo efficace di rimuovere il qualificatore const da qualsiasi tipo:

nonconst<int>::t x; 
nonconst<int const>::t y; 
assert(typeid(x) == typeid(int)); 
assert(typeid(y) == typeid(int)); 

Ci sono molti simili casi d'uso, ad esempio, per aggiungere (o rimuovere) il qualificatore puntatore da un tipo, fornire valori predefiniti e specializzazioni per determinati tipi, ecc.

Tuttavia, notare il diverso involucro dei nomi dei tipi! I tipi uguali in typedef T T sono illegali in C++. [I stare corretto: §7.1.3.2] Inoltre, lo standard di fatto denominazione (cementata dal suo uso in librerie Boost) è chiamare il nome del tipo alias type, ad esempio:

typedef T type; 
+0

"I tipi uguali in typedef T T sono illegali" - questo non è corretto. Vedi 7.1.3.2 nello standard C++ '03. –

+0

@Alex: non ne ero a conoscenza. Tuttavia, 'g ++' 4.4.2 ('-pedantic') viene richiamato quando utilizzo un involucro identico nel codice precedente. Quindi questo è un bug del compilatore? –

+0

Spiacente, penso che il gotcha possa essere nell'osservazione "non-class scope". Anche Comeau Online non lo compila, ma lo fa VC2008. Non sono riuscito a trovare il posto nello standard che lo avrebbe esplicitamente disabilitato (chiunque?), Quindi potrebbe essere definito dall'implementazione. –

1

quanto come già stato detto, funziona particolarmente bene all'interno di un modello:

template <class Foo> 
struct Bar 
{ 
    typedef Foo Foo; 
}; 

Ma può anche essere combinato con il modello di specializzazione:

template <class Foo> 
struct Bar<Foo*> 
{ 
    typedef Foo Foo; 
}; 

Ora, posso fare:

Bar<int>::Foo i = 0; 
Bar<int*>::Foo j = i; 

Bar si comporta così efficacemente come una sorta di involucro tipo, che può essere importante per la sua interfaccia (se v'è una bool equals(Foo i) const per esempio).

genere, il nome scelto ha un significato value_type per esempio ...

0

Nuova idea! Alcuni club di programmazione come uso estensivo di typedef ...

zoo/animali/types.h:

namespace zoo 
{ 
    namespace animals 
    { 
     typedef size_t Count; 
     // ... 
    } // namespace animals 
} // namespace zoo 

zoo/animali/zebra.h:

#include "zoo/animals/types.h" 

namespace zoo 
{ 
    namespace animals 
    { 
     class Zebra { 
     public: 
      typedef Count Count; 
      Count getLegCount() const; 
      // ... 
     }; // class Zebra 
    } // namespace animals 
} // namespace zoo 

main.cpp:

#include "zoo/animals/zebra.h" 

int main() 
{ 
    typedef zoo::animals::Zebra Zebra; 
    Zebra z; 
    Zebra::Count n = z.getLegCount(); 
    // Not as zoo::animals::Count 
    // No using namespace zoo::animals required, 
    // we are using just one item from there, the Zebra. 
    // Definition of Zebra::Count may change, your usage remains robust. 
    return 0; 
} 

Ho solo una situazione simile sul mio posto di lavoro. La traduzione potrebbe essere un po 'sciocca, ma volevo presentarla in fretta.