[libcxx-commits] [libcxx] [libc++] cv-qualified types in atomic and atomic_ref (P3323R1) (PR #121414)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 31 12:34:41 PST 2025


================
@@ -271,43 +311,101 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
 
   _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default;
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); }
+  _LIBCPP_HIDE_FROM_ABI value_type operator=(value_type __desired) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return __base::operator=(__desired);
+  }
 
   atomic_ref& operator=(const atomic_ref&) = delete;
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+  _LIBCPP_HIDE_FROM_ABI value_type
+  fetch_add(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+    requires(!is_const_v<value_type>)
+  {
     return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order));
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+  _LIBCPP_HIDE_FROM_ABI value_type
+  fetch_sub(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+    requires(!is_const_v<value_type>)
+  {
     return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order));
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+  _LIBCPP_HIDE_FROM_ABI value_type
+  fetch_and(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+    requires(!is_const_v<value_type>)
+  {
     return __atomic_fetch_and(this->__ptr_, __arg, std::__to_gcc_order(__order));
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+  _LIBCPP_HIDE_FROM_ABI value_type
+  fetch_or(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+    requires(!is_const_v<value_type>)
+  {
     return __atomic_fetch_or(this->__ptr_, __arg, std::__to_gcc_order(__order));
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+  _LIBCPP_HIDE_FROM_ABI value_type
+  fetch_xor(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+    requires(!is_const_v<value_type>)
+  {
     return __atomic_fetch_xor(this->__ptr_, __arg, std::__to_gcc_order(__order));
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++() const noexcept { return fetch_add(_Tp(1)) + _Tp(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--() const noexcept { return fetch_sub(_Tp(1)) - _Tp(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __arg) const noexcept { return fetch_and(__arg) & __arg; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __arg) const noexcept { return fetch_or(__arg) | __arg; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __arg) const noexcept { return fetch_xor(__arg) ^ __arg; }
+  _LIBCPP_HIDE_FROM_ABI value_type operator++(int) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_add(value_type(1));
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator--(int) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_sub(value_type(1));
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator++() const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_add(value_type(1)) + value_type(1);
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator--() const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_sub(value_type(1)) - value_type(1);
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator+=(value_type __arg) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_add(__arg) + __arg;
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator-=(value_type __arg) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_sub(__arg) - __arg;
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator&=(value_type __arg) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_and(__arg) & __arg;
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator|=(value_type __arg) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_or(__arg) | __arg;
+  }
+  _LIBCPP_HIDE_FROM_ABI value_type operator^=(value_type __arg) const noexcept
+    requires(!is_const_v<_Tp>)
+  {
+    return fetch_xor(__arg) ^ __arg;
+  }
 };
 
 template <class _Tp>
-  requires std::floating_point<_Tp>
+  requires floating_point<_Tp>
 struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
   using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>;
 
+  static_assert(__base::is_always_lock_free || !is_volatile_v<_Tp>);
----------------
ldionne wrote:

Here and above, let's add a short error message. We can maybe say that the Standard disallows this along with a rationale if there's one. As-is, users could be left thinking that it's an artifact of our implementation or something. Let's be explicit about the fact that the Standard doesn't allow it.

https://github.com/llvm/llvm-project/pull/121414


More information about the libcxx-commits mailing list