C++Guns – RoboBlog

15.02.2019

C++ Guns: class template specialization with concepts aka C++20 std::ranges::value_type

Filed under: Allgemein — Tags: — Thomas @ 20:02

You can create a constrain for a class. And another constrain for the same class. Isn't this crazy stuff?

With this we can build something like an identity function for types, like std::type_identity, for value_type. It's something like the C++17 non-member functions size() and empty(). Why must value_type be a member? It can be a non-member trait.

It turns out, there is already this functionality in C++ 20 ranges TS in std::experimental::ranges::value_type. It's really hard to catch up... but implemented it for you. And users may specialize value_type I also put my part for arithmetic types here.

This is part of ACPL functional.hpp file.

/// Primary template is an empty struct.
/// \note this is in C++20 ranges now except for the arithmetic types overload 
/// https://en.cppreference.com/w/cpp/experimental/ranges/iterator/value_type
template<class I>
struct value_type { };

/// Specialization for pointers.
/// If T is an object type, provides a member type type equal to std::remove_cv_t<T>.
///  Otherwise, there is no member type.
template<class T>
struct value_type<T*> {
  using type = std::remove_cv_t<T>;
};

/// Specialization for array types.
template<class I>
  requires(std::is_array<I>::value)
struct value_type<I> : value_type<std::decay_t<I>> { };

/// Specialization for const-qualified types.
template<class T>
struct value_type<const T> : value_type<std::decay_t<T>> { };

/// Specialization for types that define a public and accessible member type value_type.
/// If T::value_type is an object type, provides a member type type equal to T::value_type.
/// Otherwise, there is no member type.
/// \todo requires requires
template<class T>
  requires requires{ typename T::value_type; }
struct value_type<T> {
  using type = typename T::value_type;
};

/// Specialization for types that define a public and accessible member type element_type.
/// (e.g., std::shared_ptr).
/// If T::element_type is an object type, provides a member type type equal to std::remove_cv_t<typename T::element_type>.
/// Otherwise, there is no member type.
template<class T>
  requires requires{ typename T::element_type; }
struct value_type<T> {
    using type = typename T::element_type;
};

/// Helper alias template
template<class T>
using value_type_t = typename value_type<T>::type;

/// ACPL specialization for arithmetic types
template<class T>
  requires(std::is_arithmetic_v<T>)
struct value_type<T> {
    using type = T;
};

    // Specialization for pointers.
    static_assert(std::is_same_v<int, acpl::value_type_t<int*>>);
    // Specialization for array types.
    static_assert(std::is_same_v<int, acpl::value_type_t<int[]>>);
    // Specialization for const-qualified types.
    static_assert(std::is_same_v<int, acpl::value_type_t<const int*>>);
    // Specialization for types that define a public and accessible member type value_type.
    static_assert(std::is_same_v<int, acpl::value_type_t<std::array<int,1>>>);
    // Specialization for types that define a public and accessible member type element_type.
    static_assert(std::is_same_v<int, acpl::value_type_t<std::unique_ptr<int>>>);

    // ACPL specialization for arithmetic types
    static_assert(std::is_same_v<int, acpl::value_type_t<int>>);
    static_assert(std::is_same_v<int, acpl::value_type_t<const int>>);

For the record, this is my first try:

template<typename T>
struct value_type {
};

template<typename T>
requires(std::is_scalar_v<T>)
struct value_type<T> {
    using type = T;
};

template<typename T>
requires(not std::is_scalar_v<T>)
struct value_type<T> {
    using type = typename T::value_type;
};

template<typename T>
using value_type_t = typename value_type<T>::type;

static_assert(std::is_same_v<int, value_type_t<int>> );
static_assert(std::is_same_v<int, value_type_t<std::vector<int>>> );

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress