W:/Work/Software/Libraries/utl/include/utl/meta/detection.h

detection interface

Checks if Op<Args...> is a valid expression without evaluating it.

Template Parameters

  Op | a meta-callback function to pass Args...
  Args... | types to pass to Op for checking

Returns
  status of the operation [bool_]
  - true_ if Op<Args...> is valid expression
  - false_ if Op<Args...> is not valid
  // archetypal alias for a copy assignment operation
  template< class T > using copy_assign_t = decltype( declval<T&>() = declval<T const &>() );
  template< class T > using is_copy_assignable = is_detected< copy_assign_t, T >;

#ifndef __utl_meta_detection_h__
#define __utl_meta_detection_h__
#include <utl/core/impl.h>
#include <utl/meta/operations.h>
#include <type_traits>
namespace utl {
namespace meta {
#if defined(UTL_WORKAROUND_CWG_1558)
template<typename... _Ts>
struct void_ {
using type = void;
};
template<typename... _Ts>
using void_t = eval<void_<_Ts...>>;
#else
template <typename...> using void_ = void;
template <typename...> using void_t = void;
#endif
struct nat_ {
nat_() = delete;
~nat_() = delete;
nat_(nat_ const&) = delete;
void operator = (nat_ const&) = delete;
};
namespace detail {
template <typename Default,
typename AlwaysVoid,
template<typename...> class Op, typename... Args>
struct detector {
using detected = false_;
using type = Default;
};
template <typename Default,
template<typename...> class Op, typename... Args>
struct detector <Default, void_t<Op<Args...>>, Op, Args...> {
using detected = true_;
using type = Op<Args...>;
};
template <typename Default,
template<typename...> class Op, typename... Args>
using detected_or = detector<Default, void, Op, Args...>;
} // namespace detail
template <template<typename...> class Op, typename... Args>
using is_detected = typename detail::detector<nat_, void, Op, Args...>::detected;
template< template<typename...> class Op, typename... Args>
constexpr bool is_detected_v = is_detected<Op, Args...>::value;
template <template<typename...> class Op, typename... Args>
using detected_t = eval <
detail::detector<nat_, void, Op, Args...>
>;
template <typename Default,
template<typename...> class Op, typename... Args>
using detected_or_t = eval <
detail::detected_or<Default, Op, Args...>
>;
template <typename Expected,
template<typename...> class Op, typename... Args >
using is_detected_exact = eval <
same_<Expected, detected_t<Op, Args...>>
>;
template <typename Expected,
template<typename...> class Op, typename... Args >
constexpr bool is_detected_exact_v = is_detected_exact< Expected, Op, Args...>::value;
template <typename To,
template<typename...> class Op, typename... Args >
using is_detected_convertible = eval <
std::is_convertible< detected_t<Op, Args...>, To >
>;
template <typename To,
template<typename...> class Op, typename... Args >
constexpr bool is_detected_convertible_v =
is_detected_convertible<To, Op, Args...>::value;
}}
#endif /* __utl_meta_detection_h__ */