Issue 3893: LWG 3661 broke atomic<shared_ptr> a; a = nullptr; (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
3893. LWG 3661 broke atomic<shared_ptr<T>> a; a = nullptr;
Section: 32.5.8.7.2 [util.smartptr.atomic.shared] Status: WP Submitter: Zachary Wassall Opened: 2023-02-22 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [util.smartptr.atomic.shared].
View all issues with WP status.
Discussion:
LWG 3661(i), "constinit atomic<shared_ptr<T>> a(nullptr); should work" added the following to atomic<shared_ptr<T>>:
constexpr atomic(nullptr_t) noexcept : atomic() { }
I believe that doing so broke the following example:
atomic<shared_ptr> a; a = nullptr;
For reference, atomic<shared_ptr<T>> provides two assignment operator overloads:
void operator=(const atomic&) = delete; // #1 void operator=(shared_ptr desired) noexcept; // #2
Prior to LWG 3661(i), the assignment in the example unambiguously matches #2. #1 is not viable because nullptr_t is not convertible to atomic<shared_ptr<T>>. After LWG 3611, #1 is viable and the assignment is ambiguous between #1 and #2.
I believe this could be remedied easily enough by adding an assignment operator to match the added nullptr_t constructor:
void operator=(nullptr_t) noexcept;
[2023-02-25; Daniel comments and provides wording]
The suggested delegation below to store(nullptr) is not ambiguous and calls the constructorshared_ptr(nullptr_t), which is guaranteed to be no-throwing.
[2023-03-22; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2023-06-17 Approved at June 2023 meeting in Varna. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4928.
- Modify 32.5.8.7.2 [util.smartptr.atomic.shared] as indicated:
namespace std {
template struct atomic<shared_ptr> {
[…]
constexpr atomic() noexcept;
constexpr atomic(nullptr_t) noexcept : atomic() { }
atomic(shared_ptr desired) noexcept;
atomic(const atomic&) = delete;
void operator=(const atomic&) = delete;
[…]
void operator=(shared_ptr desired) noexcept;
void operator=(nullptr_t) noexcept;
[…]
private:
shared_ptr p; // exposition only
};
}[…]
void operator=(shared_ptr desired) noexcept;
-5- Effects: Equivalent to
store(desired).void operator=(nullptr_t) noexcept;
-?- Effects: Equivalent to
store(nullptr).