Concept for smart pointers

Viewed 465

Given a class template like this:

template<typename T>
struct foo
{
    T data;
};

How may one determine whether T is a smart pointer such as std::shared_ptr<T_underlying> using C++20 concepts?

I want to add functionality to foo<T> based on this criteria. For example, Instead of using SFINAE, I'd like to use the new concept system.

I want to achieve something like this:

template<typename T>
struct foo
{
    T data;

    void func()
    requires is_shared_ptr_v<T>
    {
        // ...
    }
};

Are there existing concepts for this in the STL? If not, I assume I can write a concept for std::shared_ptr, one for std::unique_ptr and so on and then tie them together with logical or in a general is_smart_pointer concept?

2 Answers

You might first create a traits to detect if type is a std::shared_ptr (way depends if you want to consider inheritance or not).

And then use the traits to build a concept:

template <typename T> struct is_shared_ptr : std::false_type {};
template <typename T> struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};

template <typename T> concept IsSharedPtr = is_shared_ptr<T>::value;

or

template <typename T>
std::true_type inherit_from_shared_ptr_impl(const std::shared_ptr<T>*);
std::false_type inherit_from_shared_ptr_impl(...);

template <typename T>
using inherit_from_shared_ptr =
    decltype(inherit_from_shared_ptr_impl(std::declval<T*>()));

template <typename T> concept InheritFromSharedPtr = inherit_from_shared_ptr<T>::value;

Write "is pointer like". Has unary dereference, explicit cast to bool, and is either a pointer or has an operator arrow. Maybe that (for non pointers) get returns the same type as operator arrow.

Then state that a smart pointer is a pointer like thing that isn't a pointer.

Note that some iterators are smart pointers under this rule.

If you want an "owning" pointer you have to have a manual trait; there is no way to tell that other than semantically.

Related