1

What is the "universal" to check a pointer is std::unique_ptr, which works with const & and custom deleters. Maybe is there any way to check all smart pointers at once?

I want to

  • write some function to check empty variant, if it contains only pointers (i.e raw, std::unique_ptr, std::shared_ptr) and
  • check instantiation of it by std::enable_if

But what I should write in condition?

template <typename... T>
std::enable_if_t<???, bool>
IsEmptyVariantOfPointers(const std::variant<T...>& variant)
{
    bool emptyVariant = true;
    std::visit([&emptyVariant](auto&& arg)
    {
        emptyVariant = arg == nullptr;
    }, variant);

    return emptyVariant;
}

NOTE: I'm interested the option without template function overloading by pointer types.

JeJo
  • 30,635
  • 6
  • 49
  • 88
isrepeat
  • 113
  • 5

1 Answers1

3

Maybe there are ways to check all smart pointers at once?

You can write a trait which checks the type of the passed template class to be a certain template class type, as follows:

template<typename Type, template<typename...> class Args>
struct is_specialization_of final : std::false_type {};

template<template<typename...> class PointerType, typename... Args>
struct is_specialization_of<PointerType<Args...>, PointerType> final: std::true_type {};

Now provide a variable template of type bool which checks the template classes (i.e. smart pointers or any customer pinter classes).

template<typename PointerType>
inline constexpr bool is_std_smart_ptr =
   is_specialization_of<PointerType, std::unique_ptr>::value
|| is_specialization_of<PointerType, std::shared_ptr>::value;

This can be used in the std::enable_if_t as follows. For simplicity, I have replaced the variadic template arguments with a simple template argument. I leave the variadic version to you.

template <typename T>
std::enable_if_t<is_std_smart_ptr<T>, bool>
IsEmptyVariantOfPointers(const std::variant<T>& variant) {
     // .....
}

What are the universal ways to check is_unique_ptr?

If the actual intention is only to find the std::unique_ptr, (one way) you can write dedicated traits for it.

template <typename...> struct is_std_unique_ptr final : std::false_type {};
template<class T, typename... Args>
struct is_std_unique_ptr<std::unique_ptr<T, Args...>> final : std::true_type {};
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 2
    What's up with `final` on traits? Inheriting one trait from another is a valid usecase. For example, [`std::conjunction`](https://en.cppreference.com/w/cpp/types/conjunction) does that. – HolyBlackCat Feb 13 '23 at 14:22
  • 1
    @HolyBlackCat Final is optional here. (IMHO) Nothing to nitpick for a silly thing. BTW fold expression comes in handy instead of `std::conjunction` or like traits as well, if the `::value` being variable templated. – JeJo Feb 13 '23 at 14:30