/*! * \file detection.h * \brief Detection idiom based on WG21's N4502[1] from Walter E. Brown * * [1]: www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf * * Copyright (C) 2018-2019 Christos Choutouridis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef __utl_meta_detection_h__ #define __utl_meta_detection_h__ #include #include #include /*! * \ingroup meta * \defgroup detection * Detection idiom support header. */ //! @{ namespace utl { namespace meta { /*! * void_t meta-function that maps a sequence of any types to the type void */ //! @{ #if defined(UTL_WORKAROUND_CWG_1558) template struct void_ { using type = void; }; //! void_t type alias template using void_t = eval>; #else //! void_ type alias template using void_ = void; //! void_t type alias template using void_t = void; #endif //! @} /*! * Not a type to use in detected idiom */ struct nat_ { nat_() = delete; ~nat_() = delete; nat_(nat_ const&) = delete; void operator = (nat_ const&) = delete; }; //! Detector for detection idiom //! @{ namespace detail { template class Op, typename... Args> struct detector { using detected = false_; using type = Default; }; template class Op, typename... Args> struct detector >, Op, Args...> { using detected = true_; using type = Op; }; //! helper for detected_or_t template class Op, typename... Args> using detected_or = detector; } // namespace detail //! @} /*! * detection interface */ //! @{ /*! * Checks if Op is a valid expression without evaluating it. * * \param Op a meta-callback function to pass Args... * \param Args... types to pass to Op for checking * \return status of the operation [bool_] * \arg true_ if Op is valid expression * \arg false_ if Op is not valid * * \example * \code * // archetypal alias for a copy assignment operation * template< class T > * using copy_assign_t = decltype( declval() = declval() ); * * template< class T > * using is_copy_assignable = is_detected< T, copy_assign_t >; * \endcode */ template class Op, typename... Args> using is_detected = typename detail::detector::detected; //! Detection predicate template< template class Op, typename... Args> constexpr bool is_detected_v = is_detected::value; //! @} /*! * Detection idiom toolkit */ //! @{ //! evaluates to evaluation of Op if it's valid and to nat_ if not template class Op, typename... Args> using detected_t = eval < detail::detector >; //! evaluates to evaluation of Op if it's valid and to \p Default if not template class Op, typename... Args> using detected_or_t = eval < detail::detected_or >; //! evaluates to true_ if evaluation of Op is \p Expected and to false_ if not template class Op, typename... Args > using is_detected_exact = same_ >; //! evaluates to true if evaluation of Op is \p Expected and to false if not template class Op, typename... Args > constexpr bool is_detected_exact_v = is_detected_exact< Expected, Op, Args...>::value; //! evaluates to true_ if evaluation of Op is convertible to \p To //! and to false_ if not template class Op, typename... Args > using is_detected_convertible = std::is_convertible< detected_t, To >; //! evaluates to true if evaluation of Op is convertible to \p To //! and to false if not template class Op, typename... Args > constexpr bool is_detected_convertible_v = is_detected_convertible::value; //! @} }} //!@} #endif /* __utl_meta_detection_h__ */