Skip to content

File forward_like.h

File List > module > utility > src > scl > utility > type_traits > forward_like.h

Go to the documentation of this file

#pragma once

#include <type_traits>

namespace scl::detail
{
    // Add const from From onto To if From is const (ignoring reference)
    template <typename From, typename To>
    using add_const_from_t =
        ::std::conditional_t<::std::is_const_v<::std::remove_reference_t<From>>, ::std::add_const_t<To>, To>;

    // Add volatile from From onto To if From is volatile (ignoring reference)
    template <typename From, typename To>
    using add_volatile_from_t =
        ::std::conditional_t<::std::is_volatile_v<::std::remove_reference_t<From>>, ::std::add_volatile_t<To>, To>;

    // Add both const and volatile from From to To (ignoring reference)
    template <typename From, typename To>
    using add_cv_from_t = add_const_from_t<From, add_volatile_from_t<From, To>>;

    // Copy ref from From onto To: if From is &, add &, if && add &&, else no reference.
    //s Don't add reference to void.
    template <typename From, typename To>
    using add_reference_like_t = ::std::conditional_t<::std::is_lvalue_reference_v<From>,
        ::std::conditional_t<::std::is_void_v<To>, To, ::std::add_lvalue_reference_t<To>>,
        ::std::conditional_t<::std::is_rvalue_reference_v<From>,
            ::std::conditional_t<::std::is_void_v<To>, To, ::std::add_rvalue_reference_t<To>>,
            To>>;

} // namespace scl::detail

namespace scl
{
    template <typename Base, typename Type>
    using forward_like_t = ::scl::detail::add_reference_like_t<Base,
        ::scl::detail::add_cv_from_t<Base, ::std::remove_reference_t<Type>>>;

    template <typename Base, typename T>
    constexpr decltype(auto) forward_like(T && t) noexcept // NOLINT(cppcoreguidelines-missing-std-forward)
    {
        return static_cast<forward_like_t<Base, T &&>>(t);
    }

} // namespace scl