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

clang compile error: use of overloaded operator '<=' is ambiguous with (nlohmann::json{{"a", 5}})["a"] <= 10 #512

Closed
ajneu opened this issue Mar 17, 2017 · 2 comments

Comments

@ajneu
Copy link

ajneu commented Mar 17, 2017

Hi,

try compile the following code with clang: clang++-3.9 -std=c++14 -o go main.cpp

// clang++-3.9 -std=c++14 -o go main.cpp

#include "json.hpp"

using json = nlohmann::json;

int main()
{
    json j;
    j["a"] = 5;

    if (j["a"] <= 10) {
        std::cout << "yip:  5 <= 10  !!" << std::endl;
    }
    return 0;
}

We get the following compile error:

main2.cpp:10:16: error: use of overloaded operator '<=' is ambiguous (with operand types 'value_type' (aka 'nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>,
      bool, long, unsigned long, double, std::allocator, adl_serializer>') and 'int')
    if (j["a"] <= 10) {
        ~~~~~~ ^  ~~
./json.hpp:6161:17: note: candidate function
    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
                ^
main2.cpp:10:16: note: built-in candidate operator<=(long long, int)
    if (j["a"] <= 10) {
               ^
main2.cpp:10:16: note: built-in candidate operator<=(__float128, int)
main2.cpp:10:16: note: built-in candidate operator<=(unsigned long, int)
main2.cpp:10:16: note: built-in candidate operator<=(unsigned int, int)
main2.cpp:10:16: note: built-in candidate operator<=(long double, int)
main2.cpp:10:16: note: built-in candidate operator<=(int, int)
main2.cpp:10:16: note: built-in candidate operator<=(unsigned long long, int)
main2.cpp:10:16: note: built-in candidate operator<=(__int128, int)
main2.cpp:10:16: note: built-in candidate operator<=(double, int)
main2.cpp:10:16: note: built-in candidate operator<=(long, int)
main2.cpp:10:16: note: built-in candidate operator<=(unsigned __int128, int)
... etc.
1 error generated.

.
.
.

But in comparision: operator== compiles fine:

// clang++-3.9 -std=c++14 -o go main.cpp

#include "json.hpp"

using json = nlohmann::json;

int main()
{
    json j;
    j["a"] = 5;

    if (j["a"] == 5) {
        std::cout << "yip:  5 == 5  !!" << std::endl;
    }
    return 0;
}

.
.
.

Checking the code we see, that operator==, has the following bool operator==(const_reference lhs, const ScalarType rhs)

but operator<=, operator<, operator>= and operator> do not have similar functions handling scalar.

Ultimately I would like to see the following compile under clang:

// clang++-3.9 -std=c++14 -o go main.cpp

#include <cassert>
#include <cstdint>
#include "json.hpp"

using json = nlohmann::json;

#define CHECK_SCALAR(LHS, OP, RHS, RES)                 \
    assert((LHS OP static_cast<  int8_t>(RHS)) == RES); \
    assert((LHS OP static_cast< uint8_t>(RHS)) == RES); \
    assert((LHS OP static_cast< int16_t>(RHS)) == RES); \
    assert((LHS OP static_cast<uint16_t>(RHS)) == RES); \
    assert((LHS OP static_cast< int32_t>(RHS)) == RES); \
    assert((LHS OP static_cast<uint32_t>(RHS)) == RES); \
    assert((LHS OP static_cast< int64_t>(RHS)) == RES); \
    assert((LHS OP static_cast<uint64_t>(RHS)) == RES); \
    assert((LHS OP static_cast<float   >(RHS)) == RES); \
    assert((LHS OP static_cast<double  >(RHS)) == RES);
    

int main()
{
    json j;
    j["a"] = 5;

    // json op scalar
    CHECK_SCALAR(j["a"], ==, 5,  true); // all good!
    CHECK_SCALAR(j["a"], !=, 4,  true); // all good!

    CHECK_SCALAR(j["a"], <=, 7,  true); // clang compile error
    CHECK_SCALAR(j["a"], < , 7,  true); // clang compile error
    CHECK_SCALAR(j["a"], >=, 3,  true); // clang compile error
    CHECK_SCALAR(j["a"], > , 3,  true); // clang compile error


    CHECK_SCALAR(j["a"], <=, 4,  false); // clang compile error
    CHECK_SCALAR(j["a"], < , 4,  false); // clang compile error
    CHECK_SCALAR(j["a"], >=, 6,  false); // clang compile error
    CHECK_SCALAR(j["a"], > , 6,  false); // clang compile error


    
    // scalar op json
    CHECK_SCALAR(5, ==, j["a"],  true); // all good!
    CHECK_SCALAR(4, !=, j["a"],  true); // all good!

    CHECK_SCALAR(7, >=, j["a"],  true); // clang compile error
    CHECK_SCALAR(7, > , j["a"],  true); // clang compile error
    CHECK_SCALAR(3, <=, j["a"],  true); // clang compile error
    CHECK_SCALAR(3, < , j["a"],  true); // clang compile error

    CHECK_SCALAR(4, >=, j["a"],  false); // clang compile error
    CHECK_SCALAR(4, > , j["a"],  false); // clang compile error
    CHECK_SCALAR(6, <=, j["a"],  false); // clang compile error
    CHECK_SCALAR(6, < , j["a"],  false); // clang compile error
    
    return 0;
}
@ajneu
Copy link
Author

ajneu commented Mar 17, 2017

PS: It seems to me that the scalar handling functions can probably be optimized.

Currently Link

        return (lhs == basic_json(rhs));

(Why create a new json, when we can pull a type out of the lhs?)

One could probably do:

        ScalarType tmp;
        from_json(lhs, tmp);
        return (tmp == rhs);

and I'm sure it can be optimized further, since we know that rhs has type ScalarType.

nlohmann added a commit that referenced this issue Apr 7, 2017
We totally forgot to implement the comparison operators other than ==
and != for scalar types. Consequently, comparing a JSON value with a
scalar type led to compile errors.
@nlohmann
Copy link
Owner

nlohmann commented Apr 7, 2017

@ajneu I'm afraid it's not so simple, because we don't always have conversions both ways, for instance when the ScalaType is const char *. Then, basic_json(lhs) works, but from_json(lhs, tmp) does not.

I added the missing comparison operators with 90273e9. If Travis and AppVeyor succeed, I shall merge this.

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Apr 7, 2017
@nlohmann nlohmann self-assigned this Apr 7, 2017
@nlohmann nlohmann added this to the Release 3.0.0 milestone Apr 7, 2017
@nlohmann nlohmann closed this as completed Apr 7, 2017
@nlohmann nlohmann removed the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Apr 7, 2017
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

2 participants