Title
std::atomic_ref<const T> can be constructed from temporaries
Status
ready
Section
[atomics.ref.generic]
Submitter
Jiang An

Created on 2025-11-11.00:00:00 last changed 7 days ago

Messages

Date: 2025-12-05.17:02:14

Proposed resolution:

This wording is relative to N5014 after application of P3860R1.

[Drafting note: The deleted overloads were mirrored from the design of `reference_wrapper` before LWG 2993. As these overloads don't participate in implicit conversion, I don't think there will be any similar issue introduced.]

  1. Modify [atomics.ref.generic.general], primary class template `atomic_ref` synopsis, as indicated:

    namespace std {
      template<class T> struct atomic_ref {
      private:
        T* ptr;               // exposition only
      public:
        […]
        constexpr explicit atomic_ref(T&);
        explicit atomic_ref(T&&) = delete;
        constexpr atomic_ref(const atomic_ref&) noexcept;
        template<class U>
          constexpr atomic_ref(const atomic_ref<U>&) noexcept;
        […]
      };
    }
    
  2. Modify [atomics.ref.int], class template `atomic_ref` integral-type specialization synopsis, as indicated:

    namespace std {
      template<> struct atomic_ref<integral-type> {
      private:
        integral-type* ptr;               // exposition only
      public:
        […]
        constexpr explicit atomic_ref(integral-type&);
        explicit atomic_ref(integral-type&&) = delete;
        constexpr atomic_ref(const atomic_ref&) noexcept;
        template<class U>
          constexpr atomic_ref(const atomic_ref<U>&) noexcept;
        […]
      };
    }
    
  3. Modify [atomics.ref.float], class template `atomic_ref` floating-point-type specialization synopsis, as indicated:

    namespace std {
      template<> struct atomic_ref<floating-point-type> {
      private:
        floating-point-type* ptr;               // exposition only
      public:
        […]
        constexpr explicit atomic_ref(floating-point-type&);
        explicit atomic_ref(floating-point-type&&) = delete;
        constexpr atomic_ref(const atomic_ref&) noexcept;
        template<class U>
          constexpr atomic_ref(const atomic_ref<U>&) noexcept;
        […]
      };
    }
    
  4. Modify [atomics.ref.pointer], class template `atomic_ref` pointer-type specialization synopsis, as indicated:

    namespace std {
      template<> struct atomic_ref<pointer-type> {
      private:
        pointer-type* ptr;               // exposition only
      public:
        […]
        constexpr explicit atomic_ref(pointer-type&);
        explicit atomic_ref(pointer-type&&) = delete;
        constexpr atomic_ref(const atomic_ref&) noexcept;
        template<class U>
          constexpr atomic_ref(const atomic_ref<U>&) noexcept;
        […]
      };
    }
    
Date: 2025-12-15.00:00:00

[ 2025-12-05; LWG telecon. Moved to Ready ]

Date: 2025-11-11.00:00:00

std::atomic_ref<T> has a constructor taking T&, so when `T` is a `const` but not `volatile` object type, the constructor parameter can be bound to a temporary expression, which doesn't seem to make sense. Even after P3860R1, explicitly constructing std::atomic_ref<const T> from std::atomic_ref<volatile T> can be well-formed with the undesired semantics when it is well-formed to instantiate std::atomic_ref<volatile T> and its operator `T` conversion function, because the construction calls the conversion function and creates a temporary object. Probably it's better to disallow such reference binding.

History
Date User Action Args
2025-12-05 17:02:14adminsetmessages: + msg15784
2025-12-05 17:02:14adminsetstatus: new -> ready
2025-11-15 12:53:06adminsetmessages: + msg15742
2025-11-11 00:00:00admincreate