This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
unique_ptr<void>::operator*
is not SFINAE-friendlySection: 20.3.1.3.5 [unique.ptr.single.observers] Status: New Submitter: Hewill Kang Opened: 2025-08-24 Last modified: 2025-08-26
Priority: Not Prioritized
View other active issues in [unique.ptr.single.observers].
View all other issues in [unique.ptr.single.observers].
View all issues with New status.
Discussion:
LWG 2762(i) added a conditional noexcept
specification to unique_ptr::operator*
to make it consistent with shared_ptr::operator*
:
constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));
This unexpectedly makes unique_ptr<void>::operator*
no longer SFINAE-friendly,
for example:
#include <memory>
template<class T> concept dereferenceable = requires(T& t) { *t; };
static_assert( dereferenceable<int *>);
static_assert(!dereferenceable<void*>);
static_assert( dereferenceable<std::shared_ptr<int >>);
static_assert(!dereferenceable<std::shared_ptr<void>>);
static_assert( dereferenceable<std::unique_ptr<int >>);
static_assert( dereferenceable<std::unique_ptr<void>>); // hard error
Given that the standard intends for operator*
of shared_ptr
and unique_ptr
to be
SFINAE-friendly based on 20.3.2.2.6 [util.smartptr.shared.obs], regardless of the value of
static_assert
, it is reasonable to assume that there should be no hard error here.
Previous resolution [SUPERSEDED]:
This wording is relative to N5014.
Modify 20.3.1.3.5 [unique.ptr.single.observers] as indicated:
constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>())see below);-1- Mandates:
-2- Preconditions:reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(*declval<pointer>())>
isfalse
.get() != nullptr
istrue
. -3- Returns:*get()
. -?- Remarks:: The exception specification is equivalent to:!requires { *declval<pointer>(); } || requires { { *declval<pointer>() } noexcept; }
[2025-08-26; Reflector discussion]
During reflector triaging it had been pointed out that a better solution would be to constrain the
operator*
directly. The proposed wording has been updated to that effect.
Proposed resolution:
This wording is relative to N5014.
Modify 20.3.1.3.5 [unique.ptr.single.observers] as indicated:
constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));-?- Constraints:
-1- Mandates:*declval<pointer>()
is a well-formed expression.reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(*declval<pointer>())>
isfalse
. -2- Preconditions:get() != nullptr
istrue
. -3- Returns:*get()
.