-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
Cannot index by key of type static constexpr const char* #171
Comments
I can confirm the bug for Clang (Apple LLVM version 7.0.2 (clang-700.1.81)) and Clang 3.7: Code: #include <json.hpp>
using nlohmann::json;
int main()
{
static constexpr const char* _VAR1 = "MyKey";
nlohmann::json j;
j[_VAR1] = 10;
} yields:
Interestingly, GCC 5.2.0 works... I shall have a look at this later. |
The ambiguity is not really between the const and the non-const version. A different program yields
|
Is the entire root of the ambiguity this function:
which allows a json to be converted to an enum? If so, should that just be removed in favor of the explicit type() function? |
I'll look into it tomorrow. |
I removed Then I tried removing |
After reading http://clang-developers.42468.n3.nabble.com/Why-doesn-t-this-compile-clang-implicit-conversions-amp-overload-resolution-td3668157.html, I added the constraint |
It seems like Clang is correct to reject the code, and the only fix I could think of is to forbid an implicit conversion of a In the end, What do you think? |
Right now, I am clueless how to fix the issue. As The use case is rather specific, I could live with closing the issue as "won't fix". |
I have a solution for this. It turns out that const char* _VAR1 = "MyKey";
nlohmann::json j;
j[_VAR1] = 10; In addition the following also cause the same problem (c style casts for brevity): char* _VAR1 = "MyKey";
j[_VAR1] = 10;
j[(const char*)"MyKey"] = 10;
j[(char*)"MyKey"] = 10; Yet these all work: char _VAR1[] = "MyKey";
j[_VAR1] = 10;
const char _VAR2[] = "MyKey";
j[_VAR2] = 10;
j[(const char)"MyKey"] = 10;
j[(char)"MyKey"] = 10; There is a clear pattern. The signature of the template we want to instantiate (the path it takes when it works) is this or its template<typename T, std::size_t n>
reference operator[](const T (&key)[n]) It would seem that this template is being rejected because for a char* there won't be a second template parameter. The compiler then ignores this one and looks to all the single parameter templates, which are all equally bad (taking integers/enums) so it gives up. The solution it would seem is to create another two template overrides in the general form: template<typename T>
reference operator[](T* key) To improve code reuse it would be better to put the actual code in this one and then call it from the char array one. There needs to be a complementary one for the const_reference case. Add this in and it compiles under both gcc and VS2015. I've pushed this to my repo if you want to see it in action. I also added some extra unit tests to check all the combinations. AppVeyor and Travis continue to pass all tests. |
Hi @twelsby, thanks for the further analysis and solution. I was missing the fact that |
@twelsby, would it be possible to open a separate PR for this issue? |
Fixed Issue #171 - added two extra template overloads of operator[] for T* arguments
This will not compile, error: use of overloaded operator '[]' is ambiguous (with operand types 'json' (aka 'basic_json<>') and 'const char *const'). Code:
The text was updated successfully, but these errors were encountered: