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

VS2017 implicit to std::string conversion fix. #464

Closed
qis opened this issue Feb 20, 2017 · 28 comments
Closed

VS2017 implicit to std::string conversion fix. #464

qis opened this issue Feb 20, 2017 · 28 comments
Assignees
Labels
kind: bug platform: visual studio related to MSVC solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Milestone

Comments

@qis
Copy link

qis commented Feb 20, 2017

Hi! Great work so far. I had to patch the library to allow implicit to-string-conversions in VS2017.

    template < typename ValueType, typename std::enable_if <
                   not std::is_pointer<ValueType>::value and
                   not std::is_same<ValueType, typename string_t::value_type>::value
//#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
                   and not std::is_same<ValueType, typename std::string_view>::value
//#endif
                   , int >::type = 0 >
    operator ValueType() const
    {
        // delegate the call to get<>() const
        return get<ValueType>();
    }

Hope this helps.

@nlohmann
Copy link
Owner

@qis Could you please try the most recent version (f2dfa09)?

nlohmann added a commit that referenced this issue Feb 20, 2017
@nlohmann
Copy link
Owner

My bad - I misunderstood your comment, so I reverted the last commit.

I cannot add the line with std::string_view to the code, because this would require C++17.

Could you please post the compiler error for the original code together with the options you are using with VS2017?

@qis
Copy link
Author

qis commented Feb 20, 2017

Here are my tests with 1a6d7f5:

#include <json.hpp>
#include <string>

int main(int argc, char* argv[]) {
  using json = nlohmann::json;
  json v  = "test";
  std::string test;
  test = v;
  return 0;
}

Compiled with /permissive- /std:c++latest /utf-8 it yields this error:

1>main.cpp
1>C:\Workspace\test\src\main.cpp(8): error C2593: 'operator =' is ambiguous
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2254): note: could be 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const _Elem)'
1>        with
1>        [
1>            _Elem=char
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2249): note: or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const _Elem *const )'
1>        with
1>        [
1>            _Elem=char
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2243): note: or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const std::basic_string_view<char,std::char_traits<char>>)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2221): note: or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2184): note: or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(std::initializer_list<_Elem>)'
1>        with
1>        [
1>            _Elem=char
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24930\include\xstring(2072): note: or       'std::basic_string<char,std::char_traits<char>,std::allocator<char>> &std::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator =(std::basic_string<char,std::char_traits<char>,std::allocator<char>> &&) noexcept(<expr>)'
1>C:\Workspace\test\src\main.cpp(8): note: while trying to match the argument list '(std::string, json)'

I propose this change:

    template < typename ValueType, typename std::enable_if <
                   not std::is_pointer<ValueType>::value and
                   not std::is_same<ValueType, typename string_t::value_type>::value
#if !defined(_MSC_VER) || _MSC_VER > 1900  // fix for issue #167 operator<< ambiguity under VS2015
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif
#if defined(_MSC_VER) && defined(_HAS_CXX17)
                   and not std::is_same<ValueType, typename std::string_view>::value
#endif
                   , int >::type = 0 >
    operator ValueType() const
    {
        // delegate the call to get<>() const
        return get<ValueType>();
    }

The _HAS_CXX17 preprocessor definition is used in <string_view> from Microsoft.

@theodelrieu
Copy link
Contributor

I shall install VS2017 and investigate that bug, we cannot put string_view in the library unfortunately.

Thanks for the report!

@nlohmann
Copy link
Owner

Thanks for the feedback. This seems to be an MSVC bug, since the code compiles with earlier versions and C++17 should not break C++11 code.

@theodelrieu
Copy link
Contributor

I'm not sure there is a good way to fix this problem, #144 fixed a similar issue, by removing the possibility to convert basic_json to char (#276).

If I understood correctly the other issues, this problem will arise whenever a class with several operator= is used on the left-hand side of operator= (I don't think this is a bug of the library, if I'm wrong, please tell me)

To me, #144 was not a good fix, for the reason mentioned above, thus I don't want to do the same thing.
However, to workaround this problem, you can still use:

  • implicit conversion by calling constructor (std::string s = j;)
  • get: s = j.get<std::string>();
  • static_cast the right-hand side of operator=

That might not suit your needs, but I really don't know if there's a way to workaround that without removing features like in #144

We should mention this problem in the README, since this might come up again, even with user-defined types.

@nlohmann
Copy link
Owner

FYI: The library is now also checked with MSVC 19.10.25017.0 / Build Engine version 15.1.548.43366 at AppVeyor, see https://ci.appveyor.com/project/nlohmann/json.

nlohmann added a commit that referenced this issue Mar 28, 2017
@nlohmann
Copy link
Owner

@qis I added the code you posted in #464 (comment) as regression test (b4dbebf). It succeeds with MSVC 2015 and 2017 in AppVeyor.

Can I close this ticket?

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Mar 28, 2017
@qis
Copy link
Author

qis commented Mar 29, 2017

@nlohmann Great! May I have until evening (UTC) to test it? Just in case I find a related problem.

@nlohmann
Copy link
Owner

Of course!

@qis
Copy link
Author

qis commented Mar 29, 2017

@nlohmann Ok, it works fine (like before) if there is no /std:c++latest compiler option present. It still requires my changes for a C++17 enabled build.

Here is a complete project for the minimal example: https://github.com/qis/json

P.S.: Just noticed that _HAS_CXX17 is always defined as 0 if C++17 is disabled or 1 if it is enabled. Updated json-c2e80a7-fixed.hpp.

@nlohmann
Copy link
Owner

nlohmann commented Mar 29, 2017

Sorry, I misunderstood. I shall add your proposed fix. I also need to add a c++latest build to AppVeyor.

@nlohmann nlohmann self-assigned this Mar 29, 2017
@nlohmann nlohmann added this to the Release 3.0.0 milestone Mar 29, 2017
@nlohmann
Copy link
Owner

nlohmann commented Apr 8, 2017

@qis I am neither expert with MSVC not with CMake. Could you give me a hint how to pass /std:c++latest to the build via cmake? Then I can add it to the AppVeyor build matrix.

@qis
Copy link
Author

qis commented Apr 9, 2017

@nlohmann You can just add it to CMAKE_CXX_FLAGS: https://github.com/qis/json/blob/master/CMakeLists.txt#L11

nlohmann added a commit that referenced this issue Apr 9, 2017
To test a fix for issue #464 (not yet implemented), we first need to
have  an MSVC build with “/permissive- /std:c++latest /utf-8”.
@nlohmann
Copy link
Owner

nlohmann commented Apr 9, 2017

Ok, got it. AppVeyor now has a configuration where MSVC 2017 is executed with the mentioned flags: https://ci.appveyor.com/project/nlohmann/json/build/1882/job/xmj9j1tlga6eeh46

Next stop: adding the fix ;)

nlohmann added a commit that referenced this issue Apr 9, 2017
@nlohmann
Copy link
Owner

nlohmann commented Apr 9, 2017

Unfortunately, the proposed fix does not work, see 628be15 and https://ci.appveyor.com/project/nlohmann/json/build/1884. It seems as if _HAS_CXX17 is also defined with MSVC 2015 and also with MSVC 2017 without defining /std:c++latest. Consequently, we get the error

C:\projects\json\src\json.hpp(3734): error C2039: 'string_view': is not a member of 'std' [C:\projects\json\test\json_unit.vcxproj]

I have to find a better way to check whether std::string_view exists.

@nlohmann
Copy link
Owner

nlohmann commented Apr 9, 2017

Ok, it's insufficient to just check whether _HAS_CXX17 is defined: it also has to have the value 1. This works now: e48114b.

@qis, could you check for yourself whether this works? Then I can merge the feature branch.

@qis
Copy link
Author

qis commented Apr 10, 2017

@nlohmann Seems to work fine in both, VS2017 and clang 4.0.0 in C++17 mode. Thank you very much for this change!

@nlohmann
Copy link
Owner

Merged the feature branch. Thanks for reporting and helping out so patiently!

@lethe555
Copy link

doesn't work in VS2015.3 ,with /std:c++latest

@nlohmann
Copy link
Owner

Could you provide an error message and the exact version?

@lethe555
Copy link

lethe555 commented Apr 19, 2017

json.hpp(3734): error C2039: 'string_view': is not a member of 'std'
in VS2015 with /std:c++latest ,_HAS_CXX17 has value of 1

#if defined(_MSC_VER) && **_MSC_VER >1900** && defined(_HAS_CXX17) && _HAS_CXX17 == 1 // fix for issue #464
                   and not std::is_same<ValueType, typename std::string_view>::value
#endif

@qis
Copy link
Author

qis commented Apr 20, 2017

@lethe555 The _MSC_VER > 1900 change you pasted fixes the problem, correct?

@lethe555
Copy link

lethe555 commented Apr 20, 2017

@qis YES . only check the value of _HAS_CXX17 is not enough

@nlohmann
Copy link
Owner

I'll have a look.

@nlohmann nlohmann reopened this Apr 20, 2017
nlohmann added a commit that referenced this issue Apr 23, 2017
needed for VS2015.3 with /std:c++latest
@nlohmann
Copy link
Owner

@lethe555 I added your proposed fix. Could you please check if it works for you?

@lethe555
Copy link

@nlohmann It works well now.

@nlohmann
Copy link
Owner

Cool, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug platform: visual studio related to MSVC solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

4 participants