From 9fb347db24ef395edccde4c959f3e4c5d3ea4126 Mon Sep 17 00:00:00 2001 From: Martchus Date: Wed, 1 Nov 2017 15:19:28 +0100 Subject: [PATCH] Add generic macro for defining (custom) type checks --- misc/traits.h | 67 +++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/misc/traits.h b/misc/traits.h index 9b41bae..e22ccf6 100644 --- a/misc/traits.h +++ b/misc/traits.h @@ -48,45 +48,38 @@ struct IsCString template struct IsString : Bool::value || IsSpecializationOf::value> { }; -/// \cond -namespace Detail { -// allow ADL with custom begin/end -using std::begin; -using std::end; -template -auto isIteratableImpl(int) -> decltype( +/*! + * \def CPP_UTILITIES_PP_COMMA + * \brief The CPP_UTILITIES_PP_COMMA macro helps passing "," as a macro argument. + */ +#define CPP_UTILITIES_PP_COMMA , + +/*! + * \def CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK + * \brief The CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK macro defines a type trait for checking whether some operation can be done with + * a particular type. + * \sa Traits::HasSize or Traits::IsIteratable for an example how to use it. + */ +#define CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(CheckName, CheckCode) \ + namespace Detail { \ + template auto CheckName(int) -> decltype(CheckCode, Bool{}); \ + template Bool CheckName(...); \ + } \ + template using CheckName = decltype(Detail::CheckName(0)) + +CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(HasSize, std::is_integral().size())>::value); +CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsReservable, std::declval().reserve(0u)); +CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsIteratable, // begin/end and operator != - begin(std::declval()) != end(std::declval()), - // operator , - void(), - // operator ++ - ++std::declval())) &>(), - // operator* - void(*begin(std::declval())), Bool{}); + std::begin(std::declval()) + != std::end(std::declval()) CPP_UTILITIES_PP_COMMA + // operator , + void() CPP_UTILITIES_PP_COMMA + // operator ++ + ++ std::declval())) &>() CPP_UTILITIES_PP_COMMA + // operator* + void(*begin(std::declval()))); -template Bool isIteratableImpl(...); -} // namespace Detail -/// \endcond - -template using IsIteratable = decltype(Detail::isIteratableImpl(0)); - -/// \cond -namespace Detail { -template auto hasSizeImpl(int) -> decltype(std::declval().size(), Bool{}); -template Bool hasSizeImpl(...); -} // namespace Detail -/// \endcond - -template using HasSize = decltype(Detail::hasSizeImpl(0)); - -/// \cond -namespace Detail { -template auto isReservable(int) -> decltype(std::declval().reserve(0u), Bool{}); -template Bool isReservable(...); -} // namespace Detail -/// \endcond - -template using IsReservable = decltype(Detail::isReservable(0)); } // namespace Traits #endif // CPP_UTILITIES_TRAITS_H