Domanda

Sto cercando di implementare una funzione di dereferenziazione del puntatore condizionale.L’idea di base è la seguente:

return is_pointer(arg) ? *arg : arg

Per limitare il numero di specializzazioni necessarie, sto tentando di utilizzare riferimenti rvalue nel caso in cui arg non è un puntatore.Ecco la mia attuale implementazione (the std::cout sono presenti esclusivamente a scopo di debug):

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T&& t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return t;
}

template< typename T >
inline typename std::enable_if< std::is_pointer< T >::value == true, typename std::remove_pointer< T >::type& >::type deref(T t)
{
    std::cout << std::is_pointer< T >::value << std::endl;
    std::cout << typeid (T).name() << std::endl;
    return *t;
}

Ora, ottengo un comportamento piuttosto strano con GCC 4.6.Il primo sovraccarico viene utilizzato sia per i tipi non puntatori che per i tipi puntatore.Ovviamente, quando si utilizza un tipo di puntatore, entra in conflitto con il secondo sovraccarico.Se commento il secondo e chiamo quanto segue utilizzando il primo...

int q;
int *p = &q;
deref(p);

...l'output della console corrispondente è:

0
Pi

Com'è possibile che un tipo non puntatore (secondo std::is_pointer) è anche un tipo di puntatore (secondo typeid) nello stesso contesto?Il conflitto sorge tra entrambi i sovraccarichi a causa di std::is_pointer segnalazione errata p come tipo non puntatore.Inoltre, quando sostituisco il riferimento del valore r con un riferimento standard nel primo sovraccarico:

inline typename std::enable_if< std::is_pointer< T >::value == false, T >::type deref(T& t)

Non è più in conflitto con il secondo sovraccarico...Semplicemente non capisco cosa stia succedendo.A proposito, utilizzando il secondo sovraccarico si ottiene (come ci si aspetterebbe):

1
Pi

Grazie per l'aiuto.

È stato utile?

Soluzione

Per quanto ho capito

template <T>
void foo(T&&)

significa che se T è un lvalue, verrà dedotto come riferimento (T = int*& nel tuo caso) e dopo il collasso dei riferimenti int*&&& restituisce un riferimento lvalue regolare int*&.Se non fosse così, questa sintassi catturerebbe qualsiasi cosa come riferimento a un valore.Considerando che il punto è associare lvalue ai riferimenti lvalue e rvalue ai riferimenti rvalue.

E is_pointer<int*&> non è vero.Quindi potresti provare a candidarti remove_reference<T>.

Altri suggerimenti

Nel tuo primo sovraccarico T viene dedotto come int*&. Prova il tuo primo sovraccarico da utilizzare remove_reference<T>::type Nel tuo abilita_if-test e output.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top