allow std::unordered_map as ObjectType

This commit is contained in:
Niels Lohmann 2021-08-19 16:08:05 +02:00
parent 44ffaa052c
commit 40483ddadb
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
4 changed files with 80 additions and 10 deletions

View File

@ -449,5 +449,23 @@ T conditional_static_cast(U value)
return value;
}
// helper to check if a type has bucket_count function (and hence can tell a std::map and a std::unordered_map apart)
template <typename T>
class has_bucket_count
{
typedef char one;
struct two
{
char x[2];
};
template <typename C> static one test( decltype(&C::bucket_count) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
} // namespace detail
} // namespace nlohmann

View File

@ -507,11 +507,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
8259](https://tools.ietf.org/html/rfc8259), because any order implements the
specified "unordered" nature of JSON objects.
*/
using object_t = ObjectType<StringType,
basic_json,
object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>;
using object_t = typename std::conditional <
detail::has_bucket_count<ObjectType<int, int>>::value,
std::unordered_map<StringType,
basic_json,
std::hash<StringType>,
std::equal_to<StringType>,
AllocatorType<std::pair<const StringType,
basic_json>>>,
std::map<StringType,
basic_json,
object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>
>::type;
/*!
@brief a type for an array

View File

@ -3858,6 +3858,24 @@ T conditional_static_cast(U value)
return value;
}
// helper to check if a type has bucket_count function (and hence can tell a std::map and a std::unordered_map apart)
template <typename T>
class has_bucket_count
{
typedef char one;
struct two
{
char x[2];
};
template <typename C> static one test( decltype(&C::bucket_count) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
} // namespace detail
} // namespace nlohmann
@ -17890,11 +17908,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
8259](https://tools.ietf.org/html/rfc8259), because any order implements the
specified "unordered" nature of JSON objects.
*/
using object_t = ObjectType<StringType,
basic_json,
object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>;
using object_t = typename std::conditional <
detail::has_bucket_count<ObjectType<int, int>>::value,
std::unordered_map<StringType,
basic_json,
std::hash<StringType>,
std::equal_to<StringType>,
AllocatorType<std::pair<const StringType,
basic_json>>>,
std::map<StringType,
basic_json,
object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>
>::type;
/*!
@brief a type for an array

View File

@ -659,6 +659,18 @@ TEST_CASE("regression tests 2")
{
static_assert(std::is_copy_assignable<nlohmann::ordered_json>::value, "");
}
SECTION("issue #2932 - Support for unordered_map as object_t")
{
using ujson = nlohmann::basic_json<std::unordered_map>;
ujson j;
j["a"] = 1;
j["b"] = 2;
CHECK(j.size() == 2);
// check that object_t is really a std::unordered_map
CHECK(ujson::object_t::hasher()("foo") == std::hash<std::string>()("foo"));
}
}
DOCTEST_CLANG_SUPPRESS_WARNING_POP