std::atomic作为std::map的值

6

我希望在一个map中使用原子变量。我正在使用Visual Studio 2012 (msvc-11)和gcc 4.7。我已经定义了一个类型:

typedef std::map<uint64_t, std::atomic<int64_t>> value_map_t;

在msvc-11中,lines
value_map_t map;
map[1] = 0;

产生错误:

错误 C2248: std::atomic<__int64>::atomic : 无法访问在类中声明的私有成员 std::atomic<__int64>

对于gcc 4.7也是如此(请参见此处)

错误:使用已删除的函数std::atomic<long int>::atomic(const std::atomic<long int>&)

然而,在Visual Studio 2013 (msvc-12)及以上版本以及gcc 4.8和更新版本中,它可以正常工作。

请自行查看gcc 4.8Visual Studio 2013+

我该怎么在msvc-11 / gcc 4.7中使其工作?


2
std::atomic 是 C++11 的一个特性,如果你不想使用支持 C++11 的编译器,那么你可能不能很好地使用这些功能。在这方面,gcc 4.7 和 msvc-11 都表现得相当不稳定。 - Chris Beck
这在2021年能用吗? - Vasantha Ganesh
gcc 4.8版本的链接已经失效。 - Antonio
2个回答

4

我没有访问Visual C++编译器的权限,但是我猜以下代码或许可行。利用映射到atomic指针的(智能)指针间接引用:

#include <atomic>
#include <map>
#include <memory>


using atomic_ptr_t = std::shared_ptr<std::atomic<int64_t>>;
typedef std::map<uint64_t, atomic_ptr_t> value_map_t;


int main()
{
    value_map_t map;
    map[1] = atomic_ptr_t(new std::atomic<int64_t>(0));

    return 0;
}

1
它确实能工作。然而,为了提高效率,避免在每次插入时使用额外的new(),以及使用.get()进行提取,这将是很好的。我想知道新编译器是如何解决这个问题的? - Vladimir Shutow
@VladimirShutow 我完全同意你的观点。再次抱歉,我无法访问这个编译器。 - Ami Tavory
如果您想要测试它,可以使用我在问题中提到的在线gcc 4.7.3编译器http://melpon.org/wandbox/permlink/J3cJEjnIygLWnkhl,但是已经感谢您提供的解决方案。 - Vladimir Shutow
4
问题似乎在于这些编译器尚未充分实现C++11的一些功能,比如这个变化,它允许 map::operator[] 默认构造映射项,而不需要任何复制/移动构造函数。 - Yam Marcovic

2

在 @Yam Marcovic 的提示下,我找到了如何在Visual Studio 2012中实现:

#include <atomic>
#include <map>
#include <tuple>

typedef std::atomic<int64_t> value_t;
typedef std::map<uint64_t, value_t> atomic_map_t;

int main()
{
    int64_t in = 5;

    atomic_map_t map;
    map.emplace(std::piecewise_construct, 
            std::forward_as_tuple(1), std::forward_as_tuple(in));

    auto it = map.find(1);
    int64_t out =  it->second.load(); 

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接