0

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.

user18490
  • 3,546
  • 4
  • 33
  • 52
  • 1
    The above code contains a definition of a function `const json_error_category_impl& json_error_category();` but no declaration of `json_error_category`. Where is the body of the function `json_error_category` ? – Richard Critten May 15 '23 at 10:55
  • 1
    `std::error_code` expects its second argument to be an object of type `std::error_category`. `json_error_category()` is a function that is expected to return a `json_error_category_impl` object which derives from `std::error_category`. However, it looks like the definition of `json_error_category()` is missing. `json_error_category_impl()` works because it is a constructor call and a temporary object of type `json_error_category_impl` gets passed. – Hari May 15 '23 at 11:00
  • @Richard Critten. Thank you. I understand. So I wasn't understanding the meaning of `const json_error_category_impl& json_error_category();` and this answers my second question. This is a **function**, not a `const reference object`. So the implementation of that function is required (hence the link error). I looked at the project code and in Json.cpp that body is indeed declared. Many thx again. If could accept your comment as an answer (and very much appreciated you answered kindly). – user18490 May 15 '23 at 11:01
  • @Richard Critten. Adding this code solves the problem. `const json_error_category_impl& json_error_category() { static json_error_category_impl instance; return instance; }` Thanks again. – user18490 May 15 '23 at 11:06

0 Answers0