123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- //
- // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/json
- //
- #ifndef BOOST_JSON_DETAIL_VALUE_TRAITS_HPP
- #define BOOST_JSON_DETAIL_VALUE_TRAITS_HPP
- #include <boost/json/detail/config.hpp>
- #include <type_traits>
- #include <tuple>
- #include <utility>
- BOOST_JSON_NS_BEGIN
- namespace detail {
- template<std::size_t N>
- struct priority_tag
- : priority_tag<N - 1> { };
- template<>
- struct priority_tag<0> { };
- using std::begin;
- using std::end;
- #ifdef __cpp_lib_nonmember_container_access
- using std::size;
- #endif
- template<typename T, typename = void>
- struct container_traits
- {
- static constexpr bool is_container = false;
- };
- template<typename T>
- struct container_traits<T, typename std::enable_if<
- std::is_same<decltype(begin(std::declval<T&>())),
- decltype(end(std::declval<T&>()))>::value>::type>
- {
- private:
- template<typename U, typename std::enable_if<
- std::is_convertible<decltype(std::declval<U&>().size()),
- std::size_t>::value>::type* = nullptr>
- static
- std::size_t
- size_impl(
- U&& cont,
- priority_tag<2>)
- {
- return cont.size();
- }
- template<typename U, typename std::enable_if<
- std::is_convertible<decltype(size(std::declval<U&>())),
- std::size_t>::value>::type* = nullptr>
- static
- std::size_t
- size_impl(
- U& cont,
- priority_tag<1>)
- {
- return size(cont);
- }
- template<typename U, std::size_t N>
- static
- std::size_t
- size_impl(
- U(&)[N],
- priority_tag<1>)
- {
- return N;
- }
- template<typename U>
- static
- std::size_t
- size_impl(U&, priority_tag<0>)
- {
- return 0;
- }
- template<typename U>
- static
- auto
- reserve_impl(
- U& cont,
- std::size_t size,
- priority_tag<1>) ->
- void_t<decltype(
- std::declval<U&>().reserve(0))>
- {
- cont.reserve(size);
- }
- template<typename U>
- static
- void
- reserve_impl(
- U&,
- std::size_t,
- priority_tag<0>) { }
- public:
- static constexpr bool is_container = true;
- using value_type = remove_cvref<
- decltype(*begin(std::declval<T&>()))>;
- template<typename U>
- static
- std::size_t
- try_size(U& cont)
- {
- return container_traits::size_impl(
- cont, priority_tag<2>());
- }
- template<typename U>
- static
- void
- try_reserve(
- U& cont,
- std::size_t size)
- {
- container_traits::reserve_impl(
- cont, size, priority_tag<1>());
- }
- };
- template<typename T, typename = void>
- struct map_traits
- {
- static constexpr bool is_map = false;
- static constexpr bool has_unique_keys = false;
- };
- template<typename T>
- struct map_traits<T, void_t<typename remove_cvref<T>::key_type,
- typename std::enable_if<container_traits<T>::is_container &&
- std::tuple_size<typename remove_cvref<T>::
- value_type>::value == 2>::type>>
- {
- private:
- template<typename U, typename = void>
- struct unique_keys : std::false_type { };
- template<typename U>
- struct unique_keys<U, typename std::enable_if<
- (std::tuple_size<remove_cvref<decltype(std::declval<
- remove_cvref<U>&>().emplace(std::declval<typename
- remove_cvref<U>::value_type>()))>>::value > 0)>::type>
- : std::true_type { };
- public:
- static constexpr bool is_map = true;
- static constexpr bool has_unique_keys = unique_keys<T>::value;
- using pair_key_type = typename std::tuple_element<
- 0, typename remove_cvref<T>::value_type>::type;
- using pair_value_type = typename std::tuple_element<
- 1, typename remove_cvref<T>::value_type>::type;
- static constexpr bool key_converts_to_string =
- std::is_convertible<pair_key_type, string_view>::value;
- };
- // does not include std::nullptr_t
- template<class T>
- using value_constructible = std::integral_constant<bool,
- std::is_same<detail::remove_cvref<T>, value>::value ||
- std::is_same<detail::remove_cvref<T>, object>::value ||
- std::is_same<detail::remove_cvref<T>, array>::value ||
- std::is_same<detail::remove_cvref<T>, string>::value ||
- std::is_same<detail::remove_cvref<T>, string_view>::value ||
- std::is_arithmetic<detail::remove_cvref<T>>::value ||
- std::is_same<detail::remove_cvref<T>, char const*>::value ||
- std::is_same<detail::remove_cvref<T>,
- std::initializer_list<value_ref>>::value ||
- std::is_same<detail::remove_cvref<T>, value_ref>::value>;
- BOOST_STATIC_ASSERT(value_constructible<value>::value);
- } // detail
- BOOST_JSON_NS_END
- #endif
|