Skip to content

File detection.h

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

Go to the documentation of this file


#pragma once

#include <type_traits>

namespace scl::detail
{
    template <typename Default, typename AlwaysVoid, template <typename...> class Operation, typename... Arguments>
    struct detector
    {
        using value_t = ::std::false_type; 
        using type = Default;              
    };

    template <typename Default, template <typename...> class Operation, typename... Arguments>
    struct detector<Default, ::std::void_t<Operation<Arguments...>>, Operation, Arguments...>
    {
        using value_t = ::std::true_type;     
        using type = Operation<Arguments...>; 
    };

} // namespace scl::detail

namespace scl
{
    template <template <typename...> class Operation, typename... Arguments>
    using is_detected = typename detail::detector<void, void, Operation, Arguments...>::value_t;

    template <template <typename...> class Operation, typename... Arguments>
    inline constexpr bool is_detected_v = is_detected<Operation, Arguments...>::value;

    template <template <typename...> class Operation, typename... Arguments>
    using detected_t = typename detail::detector<void, void, Operation, Arguments...>::type;

    template <typename Default, template <typename...> class Operation, typename... Arguments>
    using detected_or = detail::detector<Default, void, Operation, Arguments...>;

    template <typename Default, template <typename...> class Operation, typename... Arguments>
    using detected_or_t = typename detected_or<Default, Operation, Arguments...>::type;

    template <typename Expected, template <typename...> class Operation, typename... Arguments>
    using is_detected_exact = ::std::is_same<Expected, detected_t<Operation, Arguments...>>;

    template <typename Expected, template <typename...> class Operation, typename... Arguments>
    inline constexpr bool is_detected_exact_v = is_detected_exact<Expected, Operation, Arguments...>::value;

    template <typename To, template <typename...> class Operation, typename... Arguments>
    using is_detected_convertible = ::std::is_convertible<detected_t<Operation, Arguments...>, To>;

    template <typename To, template <typename...> class Operation, typename... Arguments>
    inline constexpr bool is_detected_convertible_v = is_detected_convertible<To, Operation, Arguments...>::value;

} // namespace scl