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;
|
template <typename...> using void_t = void;
|
||||||
#endif
|
#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/core/impl.h>
|
||||||
#include <utl/meta/integral.h>
|
#include <utl/meta/integral.h>
|
||||||
#include <utl/meta/void.h>
|
#include <utl/meta/detection.h>
|
||||||
#include <utl/meta/selection.h>
|
#include <utl/meta/selection.h>
|
||||||
#include <utl/meta/logical.h>
|
#include <utl/meta/logical.h>
|
||||||
|
|
||||||
|
@ -21,14 +21,13 @@
|
|||||||
#ifndef __utl_meta_meta_h__
|
#ifndef __utl_meta_meta_h__
|
||||||
#define __utl_meta_meta_h__
|
#define __utl_meta_meta_h__
|
||||||
|
|
||||||
#include <utl/meta/void.h>
|
|
||||||
#include <utl/meta/integral.h>
|
#include <utl/meta/integral.h>
|
||||||
#include <utl/meta/typelist.h>
|
#include <utl/meta/typelist.h>
|
||||||
#include <utl/meta/selection.h>
|
#include <utl/meta/selection.h>
|
||||||
#include <utl/meta/logical.h>
|
#include <utl/meta/logical.h>
|
||||||
#include <utl/meta/operations.h>
|
#include <utl/meta/operations.h>
|
||||||
#include <utl/meta/useif.h>
|
#include <utl/meta/useif.h>
|
||||||
|
#include <utl/meta/detection.h>
|
||||||
#include <utl/meta/invoke.h>
|
#include <utl/meta/invoke.h>
|
||||||
|
|
||||||
#endif /* __utl_meta_meta_h__ */
|
#endif /* __utl_meta_meta_h__ */
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <utl/core/impl.h>
|
#include <utl/core/impl.h>
|
||||||
#include <utl/meta/integral.h>
|
#include <utl/meta/integral.h>
|
||||||
#include <utl/meta/idx_sequence.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/invoke.h>
|
||||||
#include <utl/meta/sfinae.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 Foo {};
|
||||||
struct Bar {};
|
struct Bar {};
|
||||||
EXPECT_EQ(true, (std::is_same<void, void_t<int, long, Foo, Bar>>()));
|
EXPECT_EQ(true, (std::is_same<void, void_t<int, long, Foo, Bar>>()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user