As far as I am aware, there isn't any such functionionality. Inspired by this answer, it's is not too heavy to write on your own (well, you did yourself already, this variant will extend to anything providing an operator*
, though):
// first starting with some helper functions:
// return references as references!
template <typename T>
decltype(auto) doDeref(T& t, ...)
{
return t;
}
// if some custom operator* returns a temporary, we cannot bind to normal
// reference, so we'll accept as rvalue reference instead:
template <typename T>
decltype(auto) doDeref(T&& t, ...)
{
return std::move(t);
}
// specifically: anything that can be dereferenced:
template <typename T>
decltype(auto) doDeref(T& t, std::remove_reference<decltype(*t)>*)
// ^ to avoid trying to form pointer to reference
{
return doDeref(*t, nullptr);
}
// a temporary that might be dereferencable:
template <typename T>
decltype(auto) doDeref(T&& t, std::remove_reference<decltype(*t)>*)
{
return doDeref(*t, nullptr);
}
// reference wrapper; accept as const (!)
// be aware that return type still is non-const unless underlying
// type (i. e. T) is already const as well!
decltype(auto) doDeref(std::reference_wrapper<T> const& t)
{
return doDeref(t.get(), nullptr);
}
// and finally: the main functions calling the helpers:
template <typename T>
decltype(auto) deref(T& t)
{
return doDeref(t, nullptr);
}
// again to allow temporaries...
template <typename T>
decltype(auto) deref(T&& t)
{
return doDeref(std::move(t), nullptr);
}
Bonus: That's even extensible for further types that do not fit in to normal de-referencing pattern (like std::reference_wrapper
), just provide another overload calling the appropriate getter (if the class provides both const and non-const getter, you might need to provide all of the overloads for non-const and const ordinary references as well as for rvalue reference).