Boost: разыменовать аргумент шаблона, если это указатель
Что я могу использовать для разыменования аргумента шаблона, если он является указателем (или умным указателем), или оставить его как есть, если это не так?
template<class T> void subf(const T& item)
{
item.foo();
}
template<class T> void f(const T& item)
{
subf(magic_dereference_function(item));
}
Все в Boost является опцией.
4 ответа
template <typename T>
T& maybe_deref(T& x) { return x; }
template <typename T>
T& maybe_deref(T* x) { return *x; }
Вам придется добавлять перегрузки для умных указателей по отдельности. Нет способа определить, является ли класс "умным указателем". Вы могли обнаружить присутствие operator->
, но это не значит, что это умный указатель.
Как насчет перегрузки?
template<class T>
T& deref(T& t){
return t;
}
template<class T>
T& deref(T*& t){
return *t;
}
Я не знаю, подходит ли это вашему шаблону, но для ссылок на функции-члены boost:: bind и boost::phoenix уже делают то, что вы хотите:
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
_Вы даже можете использовать typetraits, чтобы сообщить boost::bind/phoenix о вашем собственном умном указателе (или любом типе, который вы хотите разыменовать с помощью operator* и operator-> при использовании)_