Skip to content

Compilation error with std::hash<gsl::not_null<std::shared_ptr<T>>> in GSL 4.2.0 #1209

Closed

Description

@lm1458777

Describe the bug
The specialization of std::hash for gsl::not_null<std::shared_ptr<T>> does not compile in GSL version 4.2.0.

To Reproduce

#include <gsl/pointers>

void test()
{
	std::hash<gsl::not_null<std::shared_ptr<int>>> hasher{};
}

Compilation Error

error C2280: 'gsl::not_null_hash<gsl::not_null<std::shared_ptr<int>>,const T &,false>::not_null_hash(void)': attempting to reference a deleted function
error C2280:         with
error C2280:         [
error C2280:             T=std::shared_ptr<int>
error C2280:         ]
    GSL-4.2.0\include\gsl\pointers(244,5):
    see declaration of 'gsl::not_null_hash<gsl::not_null<std::shared_ptr<int>>,const T &,false>::not_null_hash'
        with
        [
            T=std::shared_ptr<int>
        ]
    GSL-4.2.0\include\gsl\pointers(244,5):
    'gsl::not_null_hash<gsl::not_null<std::shared_ptr<int>>,const T &,false>::not_null_hash(void)': function was explicitly deleted
        with
        [
            T=std::shared_ptr<int>
        ]

Expected behavior
The specialization of std::hash for gsl::not_null<std::shared_ptr<T>> should compile successfully.

Spec:

  • OS: Windows
  • Compiler: MSVC 17.13.6
  • C++ Version: C++20

Additional context
In the following template from <gsl/pointers>:

template <class T, class U = decltype(std::declval<const T&>().get()), bool = std::is_default_constructible<std::hash<U>>::value>
struct not_null_hash
{
    std::size_t operator()(const T& value) const { return std::hash<U>{}(value.get()); }
};

it might be necessary to apply std::remove_cv_t<std::remove_reference_t<...>> to the type U to properly deduce the underlying type and avoid issues with const/reference qualifiers.

Activity

  1. carsonRadtke commented on May 29, 2025

    @carsonRadtke
    Member

    Thanks for reporting this issue! I'll investigate and post an update when I know more.

  2. carsonRadtke commented on Jun 2, 2025

    @carsonRadtke
    Member

    it might be necessary to apply std::remove_cv_t<std::remove_reference_t<...>> to the type U to properly deduce the underlying type and avoid issues with const/reference qualifiers.

    Yes, U was resolving to const std::shared_ptr<int> & instead of std::shared_ptr<int> which was causing further failures to the template instantiations for std::hash<T>. Your solution of applying the nested remove_* would have worked, but I think we can just use gsl::not_null<T>::element_type here instead.

  3. carsonRadtke commented on Jun 2, 2025

    @carsonRadtke
    Member

    Let's update the template for not_null_hash to grab T::element_type and use that to construct the hasher.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions