json
json copied to clipboard
(official) example for parsing "custom data source" (implementing input iterator) does not compile
Description
The example in the current section "Custom data source" does not compile with the current header. I don't know if the example or the library is erroneous (I suspect the former). But even if it is just an example I would expect it to compile - or to have an explanation of the necessary steps to make it work.
Current refers to the current develop branch.
Reproduction steps
To reproduce:
- Copy the code into a source file.
- Add the missing
#includeandusing namespace. - Optionally add dummy definition for
MyContainer::advance()andMyContainer::get_current()(does not make any difference at this stage) - Try to compile.
See result on Compiler Explorer with clang 15.0.0.
Expected vs. actual results
I would expect the code to compile (without linking) without errors.
Note: It compiles (not linking) if this call to the parser is used instead:
- json j = json::parse(c);
+ json j = json::parse(begin(c), end(c));
But the example is about using a container.
Minimal code example
++
#include <nlohmann/json.hpp>
using namespace nlohmann;
struct MyContainer {
void advance();
const char& get_current();
};
struct MyIterator {
using difference_type = std::ptrdiff_t;
using value_type = char;
using pointer = const char*;
using reference = const char&;
using iterator_category = std::input_iterator_tag;
MyIterator& operator++() {
target->advance();
return *this;
}
bool operator!=(const MyIterator& rhs) const {
return rhs.target != target;
}
reference operator*() const {
return target->get_current();
}
MyContainer* target = nullptr;
};
MyIterator begin(MyContainer& tgt) {
return MyIterator{&tgt};
}
MyIterator end(const MyContainer&) {
return {};
}
void foo() {
MyContainer c;
json j = json::parse(c);
}
Error messages
In file included from <source>:1:
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:23324:16: error: no matching function for call to 'input_adapter'
parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
^~~~~~~~~~~~~~~~~~~~~
<source>:43:20: note: in instantiation of function template specialization 'nlohmann::basic_json<>::parse<MyContainer &>' requested here
json j = json::parse(c);
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6563:27: note: candidate function not viable: no known conversion from 'MyContainer' to 'std::FILE *' (aka '_IO_FILE *') for 1st argument
inline file_input_adapter input_adapter(std::FILE* file)
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6568:29: note: candidate function not viable: no known conversion from 'MyContainer' to 'std::istream &' (aka 'basic_istream<char> &') for 1st argument
inline input_stream_adapter input_adapter(std::istream& stream)
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6573:29: note: candidate function not viable: no known conversion from 'MyContainer' to 'std::istream' (aka 'basic_istream<char>') for 1st argument
inline input_stream_adapter input_adapter(std::istream&& stream)
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6556:109: note: candidate template ignored: substitution failure [with ContainerType = MyContainer]: no type named 'adapter_type' in 'nlohmann::detail::container_input_adapter_factory_impl::container_input_adapter_factory<MyContainer>'
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
~~~~~~~~~~~~ ^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6589:32: note: candidate template ignored: requirement 'std::is_pointer<MyContainer>::value' was not satisfied [with CharT = MyContainer]
contiguous_bytes_input_adapter input_adapter(CharT b)
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6597:6: note: candidate template ignored: could not match 'T[N]' against 'MyContainer'
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
^
/app/raw.githubusercontent.com/nlohmann/json/8c391e04fe4195d8be862c97f38cfe10e2a3472e/single_include/nlohmann/json.hpp:6522:69: note: candidate function template not viable: requires 2 arguments, but 1 was provided
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
^
1 error generated.
Compiler returned: 1
Compiler and operating system
x86-64 clang 15.0.0
Library version
8c391e04fe4195d8be862c97f38cfe10e2a3472e
Validation
- [X] The bug also occurs if the latest version from the
developbranch is used. - [X] I can successfully compile and run the unit tests.
I think the issue is here:
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>
This does not allow begin() and end() to require lvalue references.
In the example those functions require lvalue references (begin(MyContainer& tgt)). This should be legitimate as std::begin() also expects lvalue references for container types. But std::declval() returns an rvalue reference by definition.