Question

J'essaie d'implémenter une fonction de déréférence de pointeur conditionnel. L'idée basique est la suivante:

return is_pointer(arg) ? *arg : arg

Afin de limiter le nombre de spécialisations nécessaires, j'essaie d'utiliser des références RValue pour le cas où arg n'est pas un pointeur. Voici mon implémentation actuelle (le std::cout Y a-t-il uniquement à des fins de débogage):

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;
}

Maintenant, j'obtiens un comportement assez étrange sous GCC 4.6. La première surcharge est utilisée à la fois pour les types de non-points et les types de pointeurs. De toute évidence, lors de l'utilisation d'un type de pointeur, il entre en conflit avec la deuxième surcharge. Si je commente le deuxième et appelle ce qui suit en utilisant le premier ...

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

... La sortie de la console correspondante est:

0
Pi

Comment est-il possible qu'un type non-pointeur (selon std::is_pointer) est également un type de pointeur (selon typeid) dans le même contexte? Le conflit se pose entre les deux surcharges dues à std::is_pointer Rapport à tort p comme type non-pointeur. De plus, lorsque je remplace la référence de valeur R par une référence standard dans la première surcharge:

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

Cela n'influence plus avec la deuxième surcharge ... Je ne comprends tout simplement pas ce qui se passe. Soit dit en passant, l'utilisation des rendements de la deuxième surcharge (comme on pouvait s'y attendre):

1
Pi

Merci de votre aide.

Était-ce utile?

La solution

Pour autant que je comprends

template <T>
void foo(T&&)

signifie que si T est une lvalue, elle sera déduite comme référence (T = int*& dans votre cas) et après l'effondrement de référence de int*&&& donne une référence LVALUE régulière int*&. Si ce n'était pas comme ça, cette syntaxe capturerait quoi que ce soit comme référence de référence. Alors que le point est de lier les LVAlues aux références et à des références aux références de référence.

Et is_pointer<int*&> ce n'est pas vrai. Par conséquent, vous pourriez essayer de postuler remove_reference<T>.

Autres conseils

Dans votre première surcharge, T est déduit comme int * &. Essayez dans votre première surcharge à utiliser remove_reference<T>::type dans votre activité et sortie en activité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top