Skip to content

Commit

Permalink
Merge pull request #2553 from jasujm/jasujm/input_adapter_custom_cont…
Browse files Browse the repository at this point in the history
…ainer

Fix compilation of input_adapter(container) in edge cases
  • Loading branch information
nlohmann committed Dec 29, 2020
2 parents dfedefb + 467f622 commit ff3863d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 13 deletions.
31 changes: 26 additions & 5 deletions include/nlohmann/detail/input/input_adapters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,35 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
}

// Convenience shorthand from container to iterator
// Enables ADL on begin(container) and end(container)
// Encloses the using declarations in namespace for not to leak them to outside scope

namespace container_input_adapter_factory_impl {

using std::begin;
using std::end;

template<typename ContainerType, typename Enable = void>
struct container_input_adapter_factory {};

template<typename ContainerType>
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))> >
{
// Enable ADL
using std::begin;
using std::end;
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));

static adapter_type create(const ContainerType& container)
{
return input_adapter(begin(container), end(container));
}
};

}

return input_adapter(begin(container), end(container));
template<typename ContainerType>
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
{
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
}

// Special cases with fast paths
Expand Down
35 changes: 28 additions & 7 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5183,14 +5183,35 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
}

// Convenience shorthand from container to iterator
// Enables ADL on begin(container) and end(container)
// Encloses the using declarations in namespace for not to leak them to outside scope

namespace container_input_adapter_factory_impl {

using std::begin;
using std::end;

template<typename ContainerType, typename Enable = void>
struct container_input_adapter_factory {};

template<typename ContainerType>
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))> >
{
// Enable ADL
using std::begin;
using std::end;
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));

static adapter_type create(const ContainerType& container)
{
return input_adapter(begin(container), end(container));
}
};

return input_adapter(begin(container), end(container));
}

template<typename ContainerType>
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
{
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
}

// Special cases with fast paths
Expand Down Expand Up @@ -16801,7 +16822,7 @@ class basic_json
detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false
)
)
{
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments);
Expand Down Expand Up @@ -25346,7 +25367,7 @@ template<>
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value&&
is_nothrow_move_assignable<nlohmann::json>::value
)
)
{
j1.swap(j2);
}
Expand Down
27 changes: 26 additions & 1 deletion test/src/unit-user_defined_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const char* end(const MyContainer& c)
return c.data + strlen(c.data);
}

TEST_CASE("Custom container")
TEST_CASE("Custom container non-member begin/end")
{

MyContainer data{"[1,2,3,4]"};
Expand All @@ -75,6 +75,31 @@ TEST_CASE("Custom container")

}

TEST_CASE("Custom container member begin/end")
{
struct MyContainer2
{
const char* data;

const char* begin() const
{
return data;
}

const char* end() const
{
return data + strlen(data);
}
};

MyContainer2 data{"[1,2,3,4]"};
json as_json = json::parse(data);
CHECK(as_json.at(0) == 1);
CHECK(as_json.at(1) == 2);
CHECK(as_json.at(2) == 3);
CHECK(as_json.at(3) == 4);
}

TEST_CASE("Custom iterator")
{
const char* raw_data = "[1,2,3,4]";
Expand Down

0 comments on commit ff3863d

Please sign in to comment.