2011-06-15 9 views
7

¿Qué puedo usar para desreferenciar un argumento de plantilla si es un puntero (o un puntero inteligente) o dejarlo como está si no lo es?Boost: desreferencia un argumento de plantilla si es un puntero

template<class T> void subf(const T& item) 
{ 
    item.foo(); 
} 

template<class T> void f(const T& item) 
{ 
    subf(magic_dereference_function(item)); 
} 

Cualquier cosa en Boost es una opción.

Respuesta

10
template <typename T> 
T& maybe_deref(T& x) { return x; } 

template <typename T> 
T& maybe_deref(T* x) { return *x; } 

Deberá agregar sobrecargas para los punteros inteligentes individualmente. No hay manera de detectar si una clase es un "puntero inteligente". Puede detectar la presencia de operator->, pero eso no significa que sea un puntero inteligente.

+0

Esto es lo que tengo en este momento. Esperé que haya una solución de puntero inteligente que no implique un gran número de código para adormecer la mente. –

+0

@Alex: No es tan insensible a la mente, ¿verdad? Por cierto, no puedo decirlo con certeza, pero lo que estás haciendo huele terriblemente mal. ¿Podría describir cuál es el propósito más amplio de esta función? Sabiendo esto, puede haber una mejor solución de alto nivel que evite la necesidad de dicha función. –

+0

Las sobrecargas 'const' no son necesarias. Sin ellos, el nombre de tipo 'T' en sí mismo se deducirá como' const' según corresponda. – fredoverflow

1
+1

"Los usuarios que deseen un rasgo para detectar punteros inteligentes deberían crear propio. Sin embargo, tenga en cuenta que no hay forma de que n general para detectar automáticamente los tipos de punteros inteligentes, por lo que dicho rasgo debería estar parcialmente especializado para cada tipo de puntero inteligente compatible ". –

2

¿Qué tal una sobrecarga?

template<class T> 
T& deref(T& t){ 
    return t; 
} 

template<class T> 
T& deref(T*& t){ 
    return *t; 
} 
0

No sé si este se adapte a su patrón, pero las referencias función miembro, boost :: bind e impulsar :: Phoenix ya hacer lo que quiera:

struct T 
{ 
     void f(int) const {} 
}; 


T instance; 
T* pointer = new T(); 
boost::shared_ptr<T> shared(new T()); 

boost::bind(& T:f, instance, 1);    // stores instance by value 
boost::bind(& T:f, boost::ref(instance), 2); // stores instance by ref 
boost::bind(& T:f, boost::cref(instance), 3); // stores instance by const ref 

boost::bind(& T:f, pointer, 4);    // dereferences the pointer 

boost::bind(& T:f, shared, 5);    // dereferences the smart pointer 

_Usted incluso puede use typetraits para permitir que boost :: bind/phoenix conozca su propio puntero inteligente (o cualquier tipo que desee desreferenciar con operator * y operator-> cuando se use) _

Cuestiones relacionadas