C++ Logo

std-proposals

Advanced search

[std-proposals] Introduction of std::is_instance type trait

From: LoS <aurumpuro_at_[hidden]>
Date: Wed, 15 Mar 2023 13:23:08 +0100
Hi,
I would want to propose a new type trait, std::is_instance. Below, there is
a draft of the proposal to explain clearer my idea.

#Motivation
The C++ standard library supplies some useful type traits. Among them,
there are std::is_same, that provides the member constant value equal to
true if T and U name the same type (not ignoring cv-qualification), and
std::is_base_of, that provides the member constant value equal to true if
Derived is derived from Base or if both are the same non-union class
(ignoring cv-qualification). However, there is not a type trait that allows
to verify whether T is an instance of U.
Consider the following example:

template <typename T, typename Alloc>
struct NodeHandle
{

[...]

    T& value() const noexcept
    { return *this->m_ptr; }

    node_pointer m_ptr;
    allocator_type m_alloc;
};

template <typename U typename V, typename Alloc>
struct NodeHandle<std::pair<U, V>, Alloc>
{

[...]

    std::pair<U, V>& value() const noexcept
    { return *this->m_ptr; }

    U& key() const noexcept
    { return this->m_ptr->first; }

    V& mapped() const noexcept
    { return this->m_ptr->second; }

    node_pointer m_ptr;
    allocator_type m_alloc;
};

It is possible to make the code more compact by creating a base class from
which the class and its partial specialization inherit common members, but
this produces two immediate side effects: inheritance makes the class non
standard-layout; inheritance makes it more difficult to change the code in
the future. An alternative approach is using std::enable_if or, if
possible, C++20's constraints, like the following:

template <typename V, typename U>
requires std::is_same_v<std::remove_cvref_t<T>, std::pair<V, U>>

However, it can be less readable, and the more complex the class, the less
readable it is.
It would be helpful to enable the last two member functions if and only if
T is an instance of std::pair using std::enable_if or, if possible, C++20's
constraints. This technique would reduce the amount of code and limit the
noise without changing the entire design.
Thus, a solution may be the following:

template <typename T, typename Alloc>
struct NodeHandle
{

[...]

    T& value() const noexcept
    { return *this->m_ptr; }

    T::first_type& key() const noexcept
     requires std::is_instance_v<T, std::pair>
    { return this->m_ptr->first; }

    T::second_type& mapped() const noexcept
     requires std::is_instance_v<T, std::pair>
    { return this->m_ptr->second; }

    node_pointer m_ptr;
    allocator_type m_alloc;
};

A custom solution may take advantage of one or more already-existing type
traits and combine them to create a custom type trait, but the creation of
that non-standard type trait is an additive work for the programmer and may
carry some bugs if the code is changed in the future or there are some
oversights.

#Proposed design
std::is_instance provides the member constant value equal to true if and
only if T is an instance (ignoring cv-qualification and reference) of class
U. Otherwise it is false.

An example of implementation is the following:

namespace detail
{

  template <typename T, template <typename...> typename U>
  struct is_instance
   : false_type {};

  template <typename... Ts, template <typename...> typename U>
  struct is_instance<U<Ts...>, U>
   : true_type {};

}

template <typename T, template <typename...> typename U>
  using is_instance = detail::is_instance<remove_cvref_t<T>, U>;

  template <typename T, template <typename...> typename U>
  inline constexpr bool is_instance_v = is_instance<T, U>::value;

(Issue) The proposed implementation does not work with non-type template
parameters for the moment.

Received on 2023-03-15 12:23:22