为何仅Visual C++中std::atomic非平凡类型?Folly库适配问题咨询
std::atomic Isn't a Trivial Type in Visual C++ (And Why This Breaks Folly's Requirements) Great questions—these are common pain points when navigating cross-compiler STL differences! Let's unpack both issues clearly.
1. Why is std::atomic non-trivial only in Visual C++?
First, let's ground ourselves in what a trivial type means in C++: a type counts as trivial if it has:
- A trivial default constructor (no user-defined logic, no non-trivial member types)
- Trivial copy/move constructors and assignment operators
- A trivial destructor
- And it follows standard-layout rules
The C++ standard doesn't require std::atomic<T> to be trivial, but it allows implementations to make it trivial if T is trivial and the compiler can handle atomic operations without adding non-trivial machinery.
GCC and Clang take this approach: their std::atomic<T> implementations use compiler intrinsics (like __atomic built-ins) directly on the underlying storage of T. There's no extra non-trivial members or functions added, so when T is trivial, std::atomic<T> meets all the trivial type criteria.
Visual C++'s STL implementation, though, makes a different choice. It adds internal bookkeeping or uses a wrapper structure that introduces non-trivial elements. For example, older versions had a non-trivial destructor for std::atomic, or included a hidden member variable that wasn't trivial. This breaks the trivial type check, even for simple T like int.
2. Why does std::is_trivial_v<std::atomic<int>> return false in Visual C++ (and why does this matter for Folly)?
Folly's hazard pointer implementation requires std::atomic<hazptr_obj*> to be trivial because it relies on trivial types for low-level optimizations—things like fast memory copying, or compatibility with raw memory operations that assume triviality.
In GCC and Clang, when T is a trivial type (like a raw pointer or int), std::atomic<T> is a thin, trivial wrapper. So std::is_trivial_v correctly returns true, satisfying Folly's requirement.
But in Visual C++, even for trivial T, the std::atomic<T> type includes non-trivial components. For instance, some versions use a base class with a non-trivial destructor, or track atomic state with a non-trivial flag. These small additions make the entire std::atomic<T> type non-trivial, hence std::is_trivial_v returns false.
The key takeaway here is that this is an implementation-specific difference, not a standard violation. The C++ standard guarantees atomic operation behavior, but leaves triviality up to the compiler as long as the core requirements are met.
内容的提问来源于stack exchange,提问作者KindDragon

