如何将boost :: atomic_store与shared_ptr< T>一起使用和shared_ptr< const T&gt ;? [英] How to use boost::atomic_store with shared_ptr<T> and shared_ptr<const T>?

查看:81
本文介绍了如何将boost :: atomic_store与shared_ptr< T>一起使用和shared_ptr< const T&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的情况下, T pcl :: PointCloud< pcl :: PointXYZ>> ,但该问题应代表任何类型的 T .下面的示例产生一个错误:

In my case T is pcl::PointCloud<pcl::PointXYZ>> but the question shoud stand for any type T. The following example produces an error:

using pc = pcl::PointCloud<pcl::PointXYZ> >;
boost::shared_ptr<pc> p(new pc);
boost::shared_ptr<const pc> const_p(new pc);

// This is legal
const_p = p;

// The atomic equivalent is not
boost::atomic_store(&const_p, p);

问题在于, boost :: atomic_store 期望两个参数都为 T * T ,但是尽管这些参数被认为是不同的类型将 p 分配给 const_p 是绝对安全的.以下内容也不起作用.

The problem is that the boost::atomic_store expects both arguments to be T* and T, but these are considered different types despite the fact that it's perfectly safe to assign p to const_p. The following doesn't work either.

boost::atomic_store(&const_p, const_cast<boost::shared_ptr<const pc> > (p));

尽管上面基本上将一个 pc * 强制转换为 const pc * ,这是绝对安全的,但它会产生关于 const_cast 不能的错误转换为其他类型.我了解,因为 pc 是模板参数,所以它被视为 shared_ptr 类型的一部分,而不是cv限定词.以下工作

Despite the above basically casting a pc* to const pc* which is perfectly safe, it produces an error about const_cast not being able to convert to different type. I understand that because pc is a template argument, it is considered part of the type of the shared_ptr and not a cv qualification. The following work

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p));

但是,它会创建一个不必要的 boost :: shared_ptr .据我了解,对于 boost :: const_pointer_cast< const pc>(p)也是如此,如果不再需要 p ,可以避免这种情况.

However, it creates an extra unecessary boost::shared_ptr. It is my understanding that the same is true for boost::const_pointer_cast<const pc>(p) This can be avoided if p is no longer needed.

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(std::move(p));

这仍然会创建一个额外的对象,但这并不重要,因为未修改引用计数,这是由于原子性而复制 shared_ptr 的昂贵部分.

This still creates an extra object but it shouldn't matter because the reference count is not modified, which is the expensive part of copying a shared_ptr on account of being atomic.

这恰好发生在我代码的非关键部分,因此我对上述情况表示满意,但我想知道以供将来参考:如果 std :: move 并非一种选择,一个人如何将 boost :: shared_ptr< T> 原子存储到 boost :: shared_ptr< const T> ,而无需创建不必要的临时文件指针?之所以应该这样做是因为可以安全地通过 const T * 查看 T ,但是我不知道该怎么做.

It just so happens that this occurs in a non-critical part of my code so I'm fine with the above, but I would like to know for future reference: If std::move was not an option, how would one atomically store a boost::shared_ptr<T> to a boost::shared_ptr<const T> without the overhead of creating an unecessary temporary pointer? It should be possible because it is safe to view a T through a const T*, but I can't figure out a way to do it.

推荐答案

我了解到,由于pc是模板参数,因此它被视为shared_ptr类型的一部分,而不是cv限定条件.

I understand that because pc is a template argument, it is considered part of the type of the shared_ptr and not a cv qualification.

是的,这被称为不可推论上下文".

Yes, this is known as "non-deducible context".

以下工作

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p));

但是,它会创建一个不必要的 boost :: shared_ptr .是我的理解同样适用于 boost :: const_pointer_cast< const pc>(p)如果p为no,则可以避免这种情况需要更长的时间.

However, it creates an extra unecessary boost::shared_ptr. It is my understanding that the same is true for boost::const_pointer_cast<const pc>(p) This can be avoided if p is no longer needed.

好吧,令人惊讶,您总是会得到副本:

Well, surprise, you always get the copy:

template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
    boost::detail::spinlock_pool<2>::scoped_lock lock( p );
    p->swap( r );
}

请注意,第二个参数是按值.这立即解决了这个难题:

Note the second parameter is by value. This, at once, solves the mystery:

在Coliru上直播

#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 
#include <boost/atomic.hpp>

namespace pcl {
    struct PointXYZ {};
    template <typename P> struct PointCloud {
    };
}

int main() {
    using pc = pcl::PointCloud<pcl::PointXYZ>;
    boost::shared_ptr<pc> p             = boost::make_shared<pc>();
    boost::shared_ptr<const pc> const_p = boost::make_shared<pc>();

    // This is legal
    const_p = p;

    // The atomic equivalent is too
    boost::atomic_store<pc const>(&const_p, p);
}

如果std :: move不是一个选项,那么如何原子存储一个boost :: shared_ptr到boost :: shared_ptr而没有创建不必要的临时指针的开销?

If std::move was not an option, how would one atomically store a boost::shared_ptr to a boost::shared_ptr without the overhead of creating an unecessary temporary pointer?

不能.以这种方式看待:加载/存储意味着可以接受无原子锁实现的琐碎操作.他们做一件事,做得很好¹.

You can't. Look at it this way: load/store are meant to be trivial operations amenable to atomic lockfree implementations. They do 1 thing, and they do it well¹.

执行隐式转换只是该功能的职责.

Doing implicit conversions is just not the responsibility of that function.

我建议使用包装函数,甚至建议使用ADL解决您自己的名称空间中的重载.

I'd suggest using a wrapper function, or even using ADL to resolve your own overload from your own namespace.

这篇关于如何将boost :: atomic_store与shared_ptr&lt; T&gt;一起使用和shared_ptr&lt; const T&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆