diff --git a/src/libipc/utility/countof.h b/src/libipc/utility/countof.h index 0fa2dd8..82c1d02 100644 --- a/src/libipc/utility/countof.h +++ b/src/libipc/utility/countof.h @@ -9,6 +9,7 @@ #include // std::size_t #include "libipc/def.h" +#include "libipc/utility/generic.h" LIBIPC_NAMESPACE_BEG_ @@ -21,14 +22,56 @@ constexpr std::size_t countof(T const (&)[N]) noexcept { return N; } -template -constexpr auto countof(C const &c) -> decltype(c.size()) { - return c.size(); -} +namespace detail { + +template +struct countof_trait_has_size { + enum : bool { value = false }; +}; template -constexpr auto countof(C const &c) -> decltype(c.Size()) { - return c.Size(); +struct countof_trait_has_size().size())>> { + enum : bool { value = true }; +}; + +template +struct countof_trait_has_Size { + enum : bool { value = false }; +}; + +template +struct countof_trait_has_Size().Size())>> { + enum : bool { value = true }; +}; + +template ::value + , bool = countof_trait_has_Size::value> +struct countof_trait; + +template +struct countof_trait { + constexpr static auto countof(C const &c) noexcept(noexcept(c.size())) { + return c.size(); + } + using return_t = decltype(countof_trait::countof(std::declval())); + enum : bool { noexcept_value = noexcept(countof_trait::countof(std::declval())) }; +}; + +template +struct countof_trait { + constexpr static auto countof(C const &c) noexcept(noexcept(c.Size())) { + return c.Size(); + } + using return_t = decltype(countof_trait::countof(std::declval())); + enum : bool { noexcept_value = noexcept(countof_trait::countof(std::declval())) }; +}; + +} // namespace detail + +template > +constexpr auto countof(C const &c) noexcept(R::noexcept_value) + -> typename R::return_t { + return R::countof(c); } LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/utility/generic.h b/src/libipc/utility/generic.h new file mode 100644 index 0000000..6481046 --- /dev/null +++ b/src/libipc/utility/generic.h @@ -0,0 +1,20 @@ +/** + * @file src/generic.h + * @author mutouyun (orz@orzz.org) + * @brief Tools for generic programming + * @date 2022-03-01 + */ +#pragma once + +#include "libipc/def.h" + +LIBIPC_NAMESPACE_BEG_ + +/** + * @brief Utility metafunction that maps a sequence of any types to the type void + * @see https://en.cppreference.com/w/cpp/types/void_t +*/ +template +using void_t = void; + +LIBIPC_NAMESPACE_END_