3

当我想实现一个功能时:

template <typename TIterator>
void doSomething(TIterator begin, TIterator end);

能够与两者一起工作:

std::vector<Widget*>

std::vector<std::shared_ptr<Widget>>

我应该如何访问底层指针?由于某种原因std::shared_ptr<Widget>不能隐式转换为Widget*,我必须使用该get()函数。这样,代码就不起作用了,std::vector<Widget*>因为Widget*没有get()功能。

我要做的是:

void functionAcceptingPointer(Widget* widget);

template <typename TIterator>
void doSomething(TIterator begin, TIterator end);
{
    std::map<double, decltype(&(**begin))> map;
    ...
    auto firstPointer = &(**begin);
    ...
    functionAcceptingPointer(&(**begin));
    ....
}

每当我需要一个普通指针时,即使用双重取消引用*后跟运算符。&

它可以完成这项工作,但我很好奇是否有一些更易读、更常用的方法来做到这一点,以及在我用丑陋的东西填充我的代码后是否有一些事情会回来困扰我&(**begin)

4

2 回答 2

11

这是我为解决此问题所做的工作:

#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);
}
于 2013-03-12T18:11:43.477 回答
3

为了增加可读性,您可以创建自己的包装器来取消引用任何(智能)指针:

template<typename T> auto raw_deref(T t) -> decltype( &**t ) { return &**t; }

这会将您的代码变成

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

当然你可以想一个比raw_deref:)更好的名字

于 2013-03-12T18:18:04.723 回答