meta: Detection idiom (part 1) from Walter Brown added
This commit is contained in:
parent
2963c008f8
commit
e974b9d43d
@ -55,7 +55,117 @@ namespace meta {
|
||||
template <typename...> 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 <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...>;
|
||||
};
|
||||
|
||||
//! helper for detected_or_t
|
||||
template <typename Default,
|
||||
template<typename...> class Op, typename... Args>
|
||||
using detected_or = detector<Default, void, Op, Args...>;
|
||||
} // namespace detail
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
* detection interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* Checks if Op<Args...> 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<Args...> is valid expression
|
||||
* \arg false_ if Op<Args...> is not valid
|
||||
*
|
||||
* \example
|
||||
* \code
|
||||
* // 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< T, copy_assign_t >;
|
||||
* \endcode
|
||||
*/
|
||||
template <template<typename...> class Op, typename... Args>
|
||||
using is_detected = typename detail::detector<nat_, void, Op, Args...>::detected;
|
||||
|
||||
//! Detection predicate
|
||||
template< template<typename...> class Op, typename... Args>
|
||||
constexpr bool is_detected_v = is_detected<Op, Args...>::value;
|
||||
//! @}
|
||||
|
||||
/*!
|
||||
* Detection idiom toolkit
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! evaluates to evaluation of Op<Args...> if it's valid and to nat_ if not
|
||||
template <template<typename...> class Op, typename... Args>
|
||||
using detected_t = eval <
|
||||
detail::detector<nat_, void, Op, Args...>
|
||||
>;
|
||||
|
||||
//! evaluates to evaluation of Op<Args...> if it's valid and to \p Default if not
|
||||
template <typename Default,
|
||||
template<typename...> class Op, typename... Args>
|
||||
using detected_or_t = eval <
|
||||
detail::detected_or<Default, Op, Args...>
|
||||
>;
|
||||
|
||||
//! evaluates to true_ if evaluation of Op<Args...> is \p Expected and to false_ if not
|
||||
template <typename Expected,
|
||||
template<typename...> class Op, typename... Args >
|
||||
using is_detected_exact = same_<Expected, detected_t<Op, Args...> >;
|
||||
|
||||
//! evaluates to true if evaluation of Op<Args...> is \p Expected and to false if not
|
||||
template <typename Expected,
|
||||
template<typename...> class Op, typename... Args >
|
||||
constexpr bool is_detected_exact_v = is_detected_exact< Expected, Op, Args...>::value;
|
||||
|
||||
//! evaluates to true_ if evaluation of Op<Args...> is convertible to \p To
|
||||
//! and to false_ if not
|
||||
template <typename To,
|
||||
template<typename...> class Op, typename... Args >
|
||||
using is_detected_convertible = std::is_convertible< detected_t<Op, Args...>, To >;
|
||||
|
||||
//! evaluates to true if evaluation of Op<Args...> is convertible to \p To
|
||||
//! and to false if not
|
||||
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_void_h__ */
|
||||
#endif /* __utl_meta_detection_h__ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include <utl/core/impl.h>
|
||||
#include <utl/meta/integral.h>
|
||||
#include <utl/meta/void.h>
|
||||
#include <utl/meta/detection.h>
|
||||
#include <utl/meta/selection.h>
|
||||
#include <utl/meta/logical.h>
|
||||
|
||||
|
@ -21,14 +21,13 @@
|
||||
#ifndef __utl_meta_meta_h__
|
||||
#define __utl_meta_meta_h__
|
||||
|
||||
#include <utl/meta/void.h>
|
||||
#include <utl/meta/integral.h>
|
||||
#include <utl/meta/typelist.h>
|
||||
#include <utl/meta/selection.h>
|
||||
#include <utl/meta/logical.h>
|
||||
#include <utl/meta/operations.h>
|
||||
#include <utl/meta/useif.h>
|
||||
|
||||
#include <utl/meta/detection.h>
|
||||
#include <utl/meta/invoke.h>
|
||||
|
||||
#endif /* __utl_meta_meta_h__ */
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <utl/core/impl.h>
|
||||
#include <utl/meta/integral.h>
|
||||
#include <utl/meta/idx_sequence.h>
|
||||
#include <utl/meta/void.h>
|
||||
#include <utl/meta/detection.h>
|
||||
#include <utl/meta/invoke.h>
|
||||
#include <utl/meta/sfinae.h>
|
||||
/*!
|
||||
|
@ -160,9 +160,9 @@ namespace test_meta {
|
||||
}
|
||||
|
||||
/*
|
||||
* Test void
|
||||
* Test void_t
|
||||
*/
|
||||
TEST(Tmeta_void, VoidType) {
|
||||
TEST(Tmeta, VoidType) {
|
||||
struct Foo {};
|
||||
struct Bar {};
|
||||
EXPECT_EQ(true, (std::is_same<void, void_t<int, long, Foo, Bar>>()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user