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

comparing to 0 literal #414

Closed
stanmihai4 opened this issue Jan 2, 2017 · 8 comments
Closed

comparing to 0 literal #414

stanmihai4 opened this issue Jan 2, 2017 · 8 comments

Comments

@stanmihai4
Copy link

stanmihai4 commented Jan 2, 2017

Hello,

Comparing to the 0 literal results calls operator==(const_reference v, std::nullptr_t) since converting to a standard type is preferred to a custom one (json).

// don't let catch decompose the expression
CHECK((json(0) == 0));
CHECK((0 == json(0)));
stanmihai4 pushed a commit to stanmihai4/json that referenced this issue Jan 2, 2017
Add a function overload for comparing to int, so that the 0 literal
is not converted to nullptr.
stanmihai4 pushed a commit to stanmihai4/json that referenced this issue Jan 2, 2017
Add a function overload for comparing to int, so that the 0 literal
is not converted to nullptr.
@stanmihai4
Copy link
Author

stanmihai4 commented Jan 3, 2017

The proposed fix fails to compiles json(0) == 0L

I guess this could be fixed with CompatibleNumberIntegerType, but the constructors are already handling all those cases, including converting a nullptr.

Just removing the operator==(const_reference v, std::nullptr_t) seems to be a better solution, unless I'm missing something.

@nlohmann
Copy link
Owner

nlohmann commented Jan 3, 2017

When operator==(const_reference v, std::nullptr_t) is removed, then j == nullptr does not work for a JSON value j.

stanmihai4 pushed a commit to stanmihai4/json that referenced this issue Jan 4, 2017
Overloading the comparison operators for nullptr isn't really needed,
since the constructor can convert nullptr to a json.
@stanmihai4
Copy link
Author

stanmihai4 commented Jan 4, 2017

The errors after removing the nullptr equality operator are on clang error: use of overloaded operator '==' is ambiguous

But clang this is not the only comparison that is failing on clang: j == 1, j < 1.2, j != 1L are all already giving ambiguous overload compile errors.

@pboettch
Copy link
Contributor

pboettch commented Jan 10, 2017

When comparing json(false) to false the default GCC (5.4.0) of Ubuntu 16.04 (gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609) also calls bool operator==(const_reference v, std::nullptr_t)`:

json j = false;
bool b = false;

std::cerr << "j == false : " << (j == false) << "\n";
std::cerr << "j == b : " << (j == b) << "\n";

Gives

j == false : 0
j == b : 1

Not so on gcc 6.2, but maybe others are affected as well.

Locally I added an explicit bool operator==(const_reference v, bool). It works.

@nlohmann
Copy link
Owner

nlohmann commented Jan 15, 2017

@pboettch I can confirm your issue with macOS Sierra's Clang. The code does not compile:

issue414.cpp:10:36: error: use of overloaded operator '==' is ambiguous (with
      operand types 'json' (aka 'basic_json<>') and 'bool')
std::cerr << "j == false : " << (j == false) << "\n";
                                 ~ ^  ~~~~~
src/json.hpp:5580:17: note: candidate function
    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
                ^
issue414.cpp:10:36: note: built-in candidate operator==(unsigned __int128, int)
std::cerr << "j == false : " << (j == false) << "\n";
                                   ^

@nlohmann
Copy link
Owner

Ideally would be a function like

template<class CompatibleType, typename std::enable_if<
             std::is_constructible<basic_json, CompatibleType>::value, int>::type = 0>
friend bool operator==(CompatibleType lhs, const_reference rhs) noexcept
{
    return (basic_json(lhs) == rhs);
}

which basically like "comparability" to "constructability".

@stanmihai4
Copy link
Author

Using std::is_constructible leads to ambiguous overloads on clang for custom classes that implement the comparison operator for json.

I updated the pull request to use std::is_scalar and the test to check for comparing to nullptr, int, unsigned, long, double and string literals.

Note that some of the added tests were previously generating compile errors due to ambiguous overloads, so for example json(1) == 1 was not compiling on clang.

nlohmann added a commit that referenced this issue Feb 16, 2017
@nlohmann nlohmann self-assigned this Feb 16, 2017
@nlohmann nlohmann added this to the Release 2.1.1 milestone Feb 16, 2017
@nlohmann
Copy link
Owner

Merged with 057b1e6. Thanks everybody!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants