2014-12-25 12 views
5

articolo del Dr.Dobb A Portable "typeof" Operator dettoPortable "typeof" del nome con il collegamento esterno

Ma non è possibile utilizzare un modello di classe per estrarre un tipo da un'espressione, come è possibile con i modelli di funzione o sovraccarichi. (Se l'espressione è un nome con collegamento esterno è possibile implementare typeof con i modelli di classe utilizzando un parametro di modello non-tipo, ma questo non è molto utile.)

è la frase in grassetto tra parentesi corretta? E se sì, come può essere usato un parametro di tipo non-tipo per trovare il tipo di un'espressione con il collegamento esterno?

+0

[Ecco il mio "tentativo"] (http://ideone.com/G9hJKl) - non funziona, quindi lo sto postando come commento. Il problema è il problema "pollo e uovo". Ora, * se potessi * in qualche modo rinviare la dichiarazione del parametro di tipo, o potresti avere 'template ', potrebbe funzionare. – milleniumbug

+0

@milleniumbug - Peccato che C++ richieda una dichiarazione modello prima che possa essere specializzata. Altrimenti potrebbe funzionare come 'template struct {typedef T type};'. – qbt937

+0

Non penso che l'autore di quell'articolo di Dr.Dobb pensasse che avrebbe potuto prendere il tipo di un'espressione come @milleniumbug stava cercando di fare, perché questo non spiegherebbe la necessità che sia un collegamento esterno. – qbt937

risposta

2

In C++ 03 non è possibile implementare typeof senza utilizzare sizeof. L'alternativa più utile è quella di estrarre il tipo usando un modello di funzione che restituisce il tipo desiderato.

template<typename T> 
struct Type 
{ 
}; 

template<typename T> 
Type<T> makeType(T) 
{ 
    return Type<T>(); 
} 


int main() 
{ 
    int i; 

    makeType(2 + 2); // Type<int> 
    makeType(&i); // Type<int*> 
} 

La seguente tecnica utilizza modelli di funzione in C++ 03 per estrarre il tipo e il valore di ogni espressione che può essere utilizzato in un argomento di template.

template<typename T, T value> 
struct NonType 
{ 
}; 


template<typename T> 
struct Type 
{ 
    template<T value> 
    static NonType<T, value> 
     makeNonType() 
    { 
     return NonType<T, value>(); 
    } 
}; 

template<typename T> 
Type<T> makeType(T) 
{ 
    return Type<T>(); 
} 


#define MAKE_NONTYPE(e) makeType(e).makeNonType<e>() 

int i; 

int main() 
{ 
    MAKE_NONTYPE(2 + 2); // NonType<int, 4> 
    MAKE_NONTYPE(&i); // NonType<int*, i> 
} 

La risposta seguente mostra un utilizzo pratico di questa tecnica per estrarre il tipo e il valore di un puntatore all'espressione funzione membro: How to allow templated functor work on both member and non-member functions

+1

In effetti ottieni un'espressione di tipo 'NonType ', ma dal momento che non hai 'typeof' o' decltype', non puoi ancora usarlo per fare riferimento a quel tipo. Mi dispiace, ma non penso che questo sia utile qui. – hvd

+0

Non è 'typeof' o' decltype', ma è un'alternativa utile per risolvere un sottoinsieme dei problemi a cui si applicano. – willj

+0

Grazie. La soluzione potrebbe essere utile. – qbt937

2

Non funziona in C++ 03 - l'approccio è in realtà senza senso, presumo che l'autore non abbia mai pensato a questa idea.

Tuttavia, con i parametri impliciti modello (come proposto per C++ 1Z) potrebbe effettivamente funzionare:

template <using typename T, T&> struct infer {using type = T;}; 

int a; 
infer<a>::type // int 

Questo ancora non rilevare se a è un riferimento.

Problemi correlati