Reputation: 13313
When I want to implement a function:
template <typename TIterator>
void doSomething(TIterator begin, TIterator end);
to be able to work with both:
std::vector<Widget*>
and
std::vector<std::shared_ptr<Widget>>
how should I access the underlying pointer? For some reason std::shared_ptr<Widget>
is not implicitly convertible to Widget*
and I have to use the get()
function. This way, the code does not work for std::vector<Widget*>
since Widget*
has no get()
function.
What I do is this:
void functionAcceptingPointer(Widget* widget);
template <typename TIterator>
void doSomething(TIterator begin, TIterator end);
{
std::map<double, decltype(&(**begin))> map;
...
auto firstPointer = &(**begin);
...
functionAcceptingPointer(&(**begin));
....
}
That is use the double dereference *
followed by the &
operator, whenever I need an ordinary pointer.
It does the job, but I am curious if there is some more readable, generally used way to do this and if there are some things that can come back to haunt me after I fill my code with ugly stuff like &(**begin)
Upvotes: 3
Views: 337
Reputation: 219185
Here's what I do to solve this problem:
#include <memory>
template <class T>
inline
T*
to_raw_pointer(T* p) noexcept
{
return p;
}
template <class Pointer>
inline
typename std::pointer_traits<typename std::remove_reference<Pointer>::type>::element_type*
to_raw_pointer(Pointer&& p) noexcept
{
return ::to_raw_pointer(p.operator->());
}
int main()
{
std::shared_ptr<int> p1(new int(1));
int* r1 = to_raw_pointer(p1);
int* p2 = new int(2);
int* r2 = to_raw_pointer(p2);
}
Upvotes: 11
Reputation: 56883
To increase the readability, you can create your own wrapper to dereference any (smart) pointer:
template<typename T> auto raw_deref(T t) -> decltype( &**t ) { return &**t; }
which would turn your code into
template <typename TIterator>
void doSomething(TIterator begin, TIterator end)
{
std::map<double, decltype(raw_deref(begin))> map;
...
auto firstPointer = raw_deref(begin);
...
functionAcceptingPointer(raw_deref(begin));
....
}
and of course you could think of a better name than raw_deref
:)
Upvotes: 3