Our <atomic> was implemented (by Benjamin IIRC) based on an early C++0x draft when the spec was still trying to be valid for both C and C++. Part of the C compatibility aspect was that std::atomic_int is allowed to be either a typedef for std::atomic<int> or a base class of it, so that a C library could define std::atomic_int and then the C++ library could make std::atomic<int> derive from that.
In the final C11 spec atomics work completely differently, and atomic_int is a typedef for _Atomic int, which is not a valid base class. So the old C++0x draft's compatibility aim is impossible, atomic_int can never be the same type in C and C++. In our implementation, std::atomic_int is a base class of std::atomic<int>, which has no benefit I can see, but causes https://gcc.gnu.org/PR60940 Rather than overloading every atomic_op() non-member function to handle the derived class and the base class, it would be simpler to just get rid of the base classes and make atomic_xxx a typedef for atomic<xxx>, as the attached patch does for atomic_{bool,char,schar}. Does anyone object to that change? If you object, are you prepared to do the work to fix PR60940? :-) [Note:- it could probably be simplified even further so atomic<char> is just: template<> struct atomic<char> : public __atomic_base<char> { using __atomic_base<char>::__atomic_base; }; But that could be done later as it wouldn't change anything observable, making atomic_char a typedef for atomic<char> is the observable and IMHO important change. -end note]
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 1fc0ebb..a591c46 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -120,12 +120,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _IntTp> struct __atomic_base; - /// atomic_char - typedef __atomic_base<char> atomic_char; - - /// atomic_schar - typedef __atomic_base<signed char> atomic_schar; - /// atomic_uchar typedef __atomic_base<unsigned char> atomic_uchar; diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index 85dc252..c58853e 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -49,21 +49,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ - /// atomic_bool + template<typename _Tp> + struct atomic; + + /// atomic<bool> // NB: No operators or fetch-operations for this type. - struct atomic_bool + template<> + struct atomic<bool> { private: __atomic_base<bool> _M_base; public: - atomic_bool() noexcept = default; - ~atomic_bool() noexcept = default; - atomic_bool(const atomic_bool&) = delete; - atomic_bool& operator=(const atomic_bool&) = delete; - atomic_bool& operator=(const atomic_bool&) volatile = delete; + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; - constexpr atomic_bool(bool __i) noexcept : _M_base(__i) { } + constexpr atomic(bool __i) noexcept : _M_base(__i) { } bool operator=(bool __i) noexcept @@ -151,6 +155,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_base.compare_exchange_strong(__i1, __i2, __m); } }; + /// atomic_bool + typedef atomic<bool> atomic_bool; + /** * @brief Generic atomic type, primary class template. @@ -485,31 +492,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; - /// Explicit specialization for bool. - template<> - struct atomic<bool> : public atomic_bool - { - typedef bool __integral_type; - typedef atomic_bool __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - }; - /// Explicit specialization for char. template<> - struct atomic<char> : public atomic_char + struct atomic<char> : public __atomic_base<char> { typedef char __integral_type; - typedef atomic_char __base_type; + typedef __atomic_base<char> __base_type; atomic() noexcept = default; ~atomic() noexcept = default; @@ -523,12 +511,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator=; }; + /// atomic_char + typedef atomic<char> atomic_char; + /// Explicit specialization for signed char. template<> - struct atomic<signed char> : public atomic_schar + struct atomic<signed char> : public __atomic_base<signed char> { typedef signed char __integral_type; - typedef atomic_schar __base_type; + typedef __atomic_base<signed char> __base_type; atomic() noexcept= default; ~atomic() noexcept = default; @@ -542,6 +533,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator=; }; + /// atomic_schar + typedef atomic<signed char> atomic_schar; + /// Explicit specialization for unsigned char. template<> struct atomic<unsigned char> : public atomic_uchar