Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialization different between gcc/clang #2311

Closed
1 of 3 tasks
rpav opened this issue Jul 25, 2020 · 7 comments
Closed
1 of 3 tasks

Initialization different between gcc/clang #2311

rpav opened this issue Jul 25, 2020 · 7 comments
Labels
kind: bug solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)

Comments

@rpav
Copy link

rpav commented Jul 25, 2020

What is the issue you have?

Initialization seems to differ between clang and gcc (have not yet tried MSVC):

json j{json::object()};

std::cout << j << std::endl; 
// GCC:   [{}]
// clang: {}

I.e., in gcc this creates an array with an object as its first element; in clang it creates an object.

Please describe the steps to reproduce the issue.

Running example: https://godbolt.org/z/7r76TE

Can you provide a small but working code example?

As above.

What is the expected behavior?

Consistent initialization between compilers for the same code.

And what is the actual behavior instead?

Different values per compiler.

Which compiler and operating system are you using?

  • Compiler: clang 10, gcc 10.1
  • Operating system: Linux
  • std: c++17

Which version of the library did you use?

  • latest release version 3.7.3
  • other release - please state the version: 3.6.0, 3.8.0, whatever "trunk" is on godbolt
  • the develop branch
@rpav rpav added the kind: bug label Jul 25, 2020
@nlohmann
Copy link
Owner

Related: #2046

@stale
Copy link

stale bot commented Aug 29, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Aug 29, 2020
@nlohmann nlohmann removed the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Aug 29, 2020
@pauljurczak
Copy link
Contributor

Here is another test case (using g++-8.4 with -std=gnu++17):

  auto v{json::to_bson(R"({"s": "string"})"_json)};
  auto j1 = json::from_bson(v);
  auto j2{json::from_bson(v)};
  cout << j1.dump() << endl;
  cout << j2.dump() << endl;
.........
{"s":"string"}
[{"s":"string"}]

@timoscs
Copy link

timoscs commented Nov 12, 2020

The same bug when parsing from a string, my MVE is

#include "json.hpp"

#include <string>
#include <iostream>

using namespace nlohmann;

int main() {
  std::string data{"{"
          "\"Key1\" : \"value\","
          "\"Key2\" : \"value2\""
        "}"
      };

    json j{json::parse(data)};

    for (const auto & obj : j.items()) {
      std::cout << "Found: " << obj.key() << " value " << obj.value() << "\n";
    }

    std::cout << "Key1 has " << j.at("Key1").get<std::string>() << "\n";
}

On gcc 10.2. the output is

Found: 0 value {"Key1":"value","Key2":"value2"}
terminate called after throwing an instance of 'nlohmann::detail::type_error'
  what():  [json.exception.type_error.304] cannot use at() with array
Key1 has Abort trap: 6

on clang 10.0.1:

Found: Key1 value "value"
Found: Key2 value "value2"
Key1 has value

The expected result would be at least consistent, to me the clang behaviour seems preferable. Tested on latest release, 3.9.1

@timoscs
Copy link

timoscs commented Nov 12, 2020

And as pointed to in the linked issues, it's actually about the brace initialization. If it were possible to have the clang behaviour on gcc, that would be nice, as then one can just consistently use braces, whereas now attention is needed to whether you're building an array/object with multiple keys, or initializing from an existing json.

Anyway, I can now work around this by using parentheses for the constructors where appropriate, i.e. the following works in the toy example (and can be used in my actual code):

#include  "json.hpp"

#include <string>
#include <iostream>

using namespace nlohmann;

int main() {
  std::string data{"{"
          "\"Key1\" : \"value\","
          "\"Key2\" : \"value2\""
        "}"
      };

    json j(json::parse(data));

    for (const auto & obj : j.items()) {
      std::cout << "Found: " << obj.key() << " value " << obj.value() << "\n";
    }

    std::cout << "Key1 has " << j.at("Key1").get<std::string>() << "\n";
}

@stale
Copy link

stale bot commented Dec 25, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Dec 25, 2020
@nlohmann nlohmann added the solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope) label Dec 30, 2020
@stale stale bot removed the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Dec 30, 2020
@Ecordonnier
Copy link

See the comments in #2583 and https://json.nlohmann.me/home/faq/#brace-initialization-yields-arrays for an explanation as to why the bug was closed as wontfix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)
Projects
None yet
Development

No branches or pull requests

5 participants