I am looking (as a learning project) at the implementation of a JSON parser made available by Microsoft as part of this (no longer maintained if I get it right) project:
https://github.com/microsoft/cpprestsdk/blob/master/Release/include/cpprest/json.h#L775
In Json.h (linked above), for error handling they use the following code:
enum json_error
{
left_over_character_in_stream = 1,
malformed_array_literal,
malformed_comment,
malformed_literal,
malformed_object_literal,
malformed_numeric_literal,
malformed_string_literal,
malformed_token,
mismatched_brances,
nesting,
unexpected_token
};
class json_error_category_impl : public std::error_category
{
public:
virtual const char* name() const CPPREST_NOEXCEPT override { return "json"; }
virtual std::string message(int ev) const override
{
switch (ev)
{
case json_error::left_over_character_in_stream:
return "Left-over characters in stream after parsing a JSON value";
case json_error::malformed_array_literal: return "Malformed array literal";
case json_error::malformed_comment: return "Malformed comment";
case json_error::malformed_literal: return "Malformed literal";
case json_error::malformed_object_literal: return "Malformed object literal";
case json_error::malformed_numeric_literal: return "Malformed numeric literal";
case json_error::malformed_string_literal: return "Malformed string literal";
case json_error::malformed_token: return "Malformed token";
case json_error::mismatched_brances: return "Mismatched braces";
case json_error::nesting: return "Nesting too deep";
case json_error::unexpected_token: return "Unexpected token";
default: return "Unknown json error";
}
}
};
const json_error_category_impl& json_error_category();
Then in Json_parsing.cpp
:
https://github.com/microsoft/cpprestsdk/blob/master/Release/src/json/json_parsing.cpp
They use that code as follows:
template<typename Token>
void SetErrorCode(Token& tk, json_error jsonErrorCode)
{
tk.m_error = std::error_code(jsonErrorCode, json_error_category());
}
When I compile this code I have the following error message:
JsonParsing-cb51bd.o : error LNK2019: unresolved external symbol "class json_error_category_impl const & __cdecl json_error_category(void)" (?json_error_category@@YAAEBVjson_error_category_impl@@XZ) referenced in function "void __cdecl SetErrorCode<struct JSONParser<char>::Token>(struct JSONParser<char>::Token &,enum json_error)" (??$SetErrorCode@UToken@?$JSONParser@D@@@@YAXAEAUToken@?$JSONParser@D@@W4json_error@@@Z)
JsonParsing : fatal error LNK1120: 1 unresolved externals
clang++: error: linker command failed with exit code 1120 (use -v to see invocation)
If I replace:
tk.m_error = std::error_code(jsonErrorCode, json_error_category());
with
tk.error = std::error_code(jsonErrorCode, json_error_category_impl());
It compiles fine.
Why do I get the linker failed error, and what can I do to make this work as written in the original code?
As a side question:
I looked at:
https://en.cppreference.com/w/cpp/error/error_code/error_code. While I think I understand what that declaration does:
const json_error_category_impl& json_error_category();
Creating a const reference object of type json_error_category_impl, am I correct? (which is what the ctor of std::error_code
expects), json_error_category
is already a built const referenced object; and so, I also don't understand the use of the parenthesis in json_error_category()
.
tk.error = std::error_code(jsonErrorCode, json_error_category());
Why not just:
tk.error = std::error_code(jsonErrorCode, json_error_category);
if you could also clarify this point, it would be great.