首页 > 解决方案 > template-specializaiton for a derived std::atomic-class

问题描述

I needed an atomic that has a copy-constructor because I have a vector of objects which include an atomic. The synch-state of the atomic isn't needed to be copied of course, but the contents. I didn't really need to copy objects but I have a vector which is resized from zero to N and ::resize relies on the copy-constructor naturally since it is not only built to resize vom zero. emplace_back wouldn't help also because it also conditionally resizes the vector and thereby calls the copy-constructor.

[EDIT]:

The "specialization" for integer-types would be this:

#include <atomic>
#include <type_traits>

template <typename T, typename T2 = typename std::enable_if<std::is_integral<T>::value, T>::type>
struct xatomic : public std::atomic<T>
{
    xatomic() = default;
    xatomic( xatomic const &xa );

    using std::atomic<T>::operator =;
    using std::atomic<T>::is_lock_free;
    using std::atomic<T>::store;
    using std::atomic<T>::load;
    using std::atomic<T>::operator T;
    using std::atomic<T>::exchange;
    using std::atomic<T>::compare_exchange_weak;
    using std::atomic<T>::compare_exchange_strong;
    using std::atomic<T>::fetch_add;
    using std::atomic<T>::fetch_sub;
    using std::atomic<T>::operator ++;
    using std::atomic<T>::operator --;
    using std::atomic<T>::operator +=;
    using std::atomic<T>::operator -=;
    using std::atomic<T>::fetch_and;
    using std::atomic<T>::fetch_or;
    using std::atomic<T>::fetch_xor;
    using std::atomic<T>::operator &=;
    using std::atomic<T>::operator |=;
    using std::atomic<T>::operator ^=;
};

 template<typename T, typename T2>
inline
xatomic<T, T2>::xatomic( xatomic const &xa )
{
    *this = (T)xa;
}

But how can I have a non-intger "specialization"?

标签: c++

解决方案


与其将复制语义反向移植到atomic类型(可以看出这并不容易,即使可能的话),另一种解决方案是避免复制它们。

从评论看来,您只需要在启动/初始化时使用它,并且因为vector::resize()需要它。所以我们可以通过各种方式避免这个问题。
例如:

  1. 计算你需要多少atomic个 s,然后一次创建它们。

    int n = 100;
    std::vector<std::atomic<int>> vec(n); // does not involve copying
    

    这是因为vector<T>(size_t n),T只需要DefaultConstructible

  2. 如果atomic是较大结构的一部分,请创建一个自定义复制构造函数,以正确初始化所有atomic成员而不是复制它们。

  3. 使用在调整大小时不会移动元素的数据结构。例如,std::liststd::deque


关于以下内容的附加说明vector<atomic<int>>:将不相关线程的数据存储得太近会导致错误共享。因此,从性能的角度来看,像这样的数据结构vector<atomic<int>>可能不是一个好主意。


推荐阅读