Add generic macro for defining (custom) type checks

This commit is contained in:
Martchus 2017-11-01 15:19:28 +01:00
parent 34f3ebb45d
commit 9fb347db24
1 changed files with 30 additions and 37 deletions

View File

@ -48,45 +48,38 @@ struct IsCString
template <typename T> struct IsString : Bool<IsCString<T>::value || IsSpecializationOf<T, std::basic_string>::value> { template <typename T> struct IsString : Bool<IsCString<T>::value || IsSpecializationOf<T, std::basic_string>::value> {
}; };
/// \cond /*!
namespace Detail { * \def CPP_UTILITIES_PP_COMMA
// allow ADL with custom begin/end * \brief The CPP_UTILITIES_PP_COMMA macro helps passing "," as a macro argument.
using std::begin; */
using std::end; #define CPP_UTILITIES_PP_COMMA ,
template <typename T>
auto isIteratableImpl(int) -> decltype( /*!
* \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 <typename T> auto CheckName(int) -> decltype(CheckCode, Bool<true>{}); \
template <typename T> Bool<false> CheckName(...); \
} \
template <typename T> using CheckName = decltype(Detail::CheckName<T>(0))
CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(HasSize, std::is_integral<decltype(std::declval<T &>().size())>::value);
CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsReservable, std::declval<T &>().reserve(0u));
CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsIteratable,
// begin/end and operator != // begin/end and operator !=
begin(std::declval<T &>()) != end(std::declval<T &>()), std::begin(std::declval<T &>())
// operator , != std::end(std::declval<T &>()) CPP_UTILITIES_PP_COMMA
void(), // operator ,
// operator ++ void() CPP_UTILITIES_PP_COMMA
++std::declval<decltype(begin(std::declval<T &>())) &>(), // operator ++
// operator* ++ std::declval<decltype(begin(std::declval<T &>())) &>() CPP_UTILITIES_PP_COMMA
void(*begin(std::declval<T &>())), Bool<true>{}); // operator*
void(*begin(std::declval<T &>())));
template <typename T> Bool<false> isIteratableImpl(...);
} // namespace Detail
/// \endcond
template <typename T> using IsIteratable = decltype(Detail::isIteratableImpl<T>(0));
/// \cond
namespace Detail {
template <typename T> auto hasSizeImpl(int) -> decltype(std::declval<T &>().size(), Bool<true>{});
template <typename T> Bool<false> hasSizeImpl(...);
} // namespace Detail
/// \endcond
template <typename T> using HasSize = decltype(Detail::hasSizeImpl<T>(0));
/// \cond
namespace Detail {
template <typename T> auto isReservable(int) -> decltype(std::declval<T &>().reserve(0u), Bool<true>{});
template <typename T> Bool<false> isReservable(...);
} // namespace Detail
/// \endcond
template <typename T> using IsReservable = decltype(Detail::isReservable<T>(0));
} // namespace Traits } // namespace Traits
#endif // CPP_UTILITIES_TRAITS_H #endif // CPP_UTILITIES_TRAITS_H