std :: atomic trivially copyable structs

时间:2016-11-22 10:23:39

标签: c++ c++11 g++ c++14 atomic

C ++参考说:http://en.cppreference.com/w/cpp/atomic/atomic

  

std :: atomic可以使用任何TriviallyCopyable类型T

进行实例化

但是下面的例子在g ++ 6.2.0下不起作用

#include <atomic>
#include <functional>

struct Test11 {
    int x;
};
struct Test12 {
    char x;
};
struct Test13 {
    long x;
};
struct Test2 {
    char x;
    int y;
};
struct Test3 {
    int y;
    long x;
};

template<typename T, typename... ARGS>
void test(ARGS&& ... args) {
    static_assert(std::is_trivially_copyable<T>::value);

    std::atomic<T> a;
    a.store(T{std::forward<ARGS>(args)...});
}

int main() {
    test<Test11>(1);
    test<Test12>('\1');
    test<Test13>(1L);
    test<Test2>('\1',2);
    test<Test3>(1,2L);
    return 0;
}

编译:{{1​​}}

  

/tmp/cchademz.o:在函数g++-6 -std=c++14 -latomic test.cpp中:   test.cpp :(。text._ZNSt6atomicI5Test3E5storeES0_St12memory_order [_ZNSt6atomicI5Test3E5storeES0_St12memory_order] + 0x3e):对std::atomic<Test3>::store(Test3, std::memory_order)的未定义引用   collect2:错误:ld返回1退出状态

__atomic_store_16

  

g ++(Ubuntu 6.2.0-7ubuntu11)6.2.0 20161018

特别是我不明白为什么g++-6 --version有效但Test2没有。

有什么想法吗?

编辑:添加-latomic flag和g ++ version

1 个答案:

答案 0 :(得分:4)

如@TartanLlama在其现已删除的answer中所述,您需要链接 function PainelViewModel() { var self = this; self.Curriculos = ko.observableArray([]); self.CurriculoSelected = ko.observable(0); self.CurriculosChanged = function (c) { console.debug(c.CurriculoSelected); }; }

libatomic

您需要在编译行末尾添加g++-6 -std=c++14 test.cpp -latomic 。如果您将-latomic放在-latomic之前(例如test.cpp在Coliru上),某些编译器(链接器)可能会正常工作,但有些编译器不会(请参阅Why does the order in which libraries are linked sometimes cause errors in GCC?)。< / p>

免责声明:我不是联系方面的专家,因此我无法在某些平台上提供有关g++之前的原因的详细解释,而不是其他平台(我猜接头是不同的,但......)。

如果删除-latomic,为什么代码会编译,这取决于编译器和体系结构。如果您在 godbolt 上查看生成的ASM Test3-O2

g++6.2

您可以看到,对于少于8个字节(sub rsp, 24 movabs rax, 8589934593 mov ecx, 5 mov DWORD PTR [rsp], 1 mov rdi, rsp mov esi, 1 mov edx, 2 mfence mov BYTE PTR [rsp], 1 mfence mov QWORD PTR [rsp], 1 mfence mov QWORD PTR [rsp], rax mfence call __atomic_store_16 Test1X)的结构,编译器可以使用Test2指令(在当今架构中,qword通常为8个字节长) ),但它不能生成单个指令来处理大小严格大于8的情况(mov QWORD通常为16)。

基本上,当sizeof(Test3)std::atomic<T>时,std::atomic<T> 1 中可能会g++(或T的某些操作)专门化#34;小&#34;,&#34;小&#34;的定义可能是建筑依赖的。

免责声明:同样,我不是关于<atomic>的专家,所以这主要来自关于Godbolt上生成的ASM以及g++clang行为的实验在Coliru。

1 clang有一个__atomic_store_8程序和一个__atomic_store程序,没有-latomic它将无法为{{Test2进行编译1}}和Test3。但是,即使Test13为8,它也会设法编译sizeof(Test13),因此它不会对某些结构使用__atomic_store_8icc具有完全不同的行为,并且不生成任何call(无法在Coliru上进行测试,但您可以在Godbolt上查找)。