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

Compilation error with strong typed enums in map in combination with namespaces #1079

Closed
an-ky opened this issue May 7, 2018 · 1 comment · Fixed by #1089
Closed

Compilation error with strong typed enums in map in combination with namespaces #1079

an-ky opened this issue May 7, 2018 · 1 comment · Fixed by #1089

Comments

@an-ky
Copy link

an-ky commented May 7, 2018

  • What is the issue you have?
    Compilation error.

  • Please describe the steps to reproduce the issue. Can you provide a small but working code example?
    Compiling the small program below results in C2166: l-value specifies const object (see full compiler output below). When putting the map and the to/from_json in the same namespace it compiles. It boilds down to an assignment/construction of the map's value type.

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

namespace bla
{
enum class foo : uint16_t
{
	bar, baz
};
} // comment this out and the lines above main in and it will compile
using foo_map = std::map<foo, std::string>;

void to_json(nlohmann::json& j, const foo_map& m)
{

}

void from_json(const nlohmann::json& j, foo_map& m)
{

}
//}
//using bla::foo_map;
int main(int, char**)
{
	nlohmann::json j;
	foo_map m = j;
}
  • What is the expected behavior?
    It should compile without errors

  • And what is the actual behavior instead?
    Compilation errors

compiling main.cpp
C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/bin/HostX64/x64/cl.exe /nologo /c /EHsc /Od /Zi /MDd "/IC:\Program Files (x86)\IntelSWTools\compilers_and_libraries\windows\ipp\include" /IC:\Qt\Qt5.9.5\5.9.5\msvc2017_64\include /IC:\Qt\Qt5.9.5\5.9.5\msvc2017_64\include\QtCore /IC:\Qt\Qt5.9.5\5.9.5\msvc2017_64\mkspecs\win32-msvc /IC:\Projekte\monalysis\Entwicklung\Quellen\Projekte\build-scratchpad-VC17ohneQt-Debug\qtc_VC17_91031919-debug\scratchpad.a434f584\qt.headers /IC:\Projekte\thirdparty\boost /IC:\Projekte\thirdparty\fmt /IC:\Projekte\thirdparty\json /IC:\Projekte\thirdparty\nonius\nonius /IC:\Projekte\thirdparty\range-v3\range-v3-vs2015\include /DUNICODE /D_UNICODE /DWIN32 /DQT_CORE_LIB /DBOOST_LIB_DIAGNOSTIC /DBOOST_AUTO_LINK_TAGGED /DBOOST_RESULT_OF_USE_DECLTYPE /DBOOST_QT_PUSHBACK_WORKAROUND "/DBOOST_QT_LISTOF_WORKAROUND=1" "/DWINVER=0x0502" "/D_WIN32_WINNT=0x0502" "/D_WIN32_WINDOWS=0x0502" /FoC:\Projekte\monalysis\Entwicklung\Quellen\Projekte\build-scratchpad-VC17ohneQt-Debug\qtc_VC17_91031919-debug\scratchpad.a434f584\3a52ce780950d4d9\main.cpp.obj C:\Projekte\monalysis\Entwicklung\Quellen\Projekte\scratchpad\main.cpp /TP /FS /permissive- /std:c++latest /Zm200
:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\utility(268): error C2166: l-value specifies const object
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\utility(267): note: while compiling class template member function 'std::pair<const _Kty,_Ty> &std::pair<const _Kty,_Ty>::operator =(std::pair<const _Kty,_Ty> &&) noexcept(false)'
        with
        [
            _Kty=bla::foo,
            _Ty=std::string
        ]
C:\Projekte\monalysis\Entwicklung\Quellen\Projekte\monalysis-porsche\thirdparty\json\json/json.hpp(1172): note: see reference to function template instantiation 'std::pair<const _Kty,_Ty> &std::pair<const _Kty,_Ty>::operator =(std::pair<const _Kty,_Ty> &&) noexcept(false)' being compiled
        with
        [
            _Kty=bla::foo,
            _Ty=std::string
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\xtree(443): note: see reference to class template instantiation 'std::pair<const _Kty,_Ty>' being compiled
        with
        [
            _Kty=bla::foo,
            _Ty=std::string
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\xtree(739): note: see reference to class template instantiation 'std::_Tree_node<std::pair<const _Kty,_Ty>,std::_Default_allocator_traits<_Alloc>::void_pointer>' being compiled
        with
        [
            _Kty=bla::foo,
            _Ty=std::string,
            _Alloc=std::allocator<std::pair<const bla::foo,std::string>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\xtree(738): note: while compiling class template member function 'void std::_Tree_comp_alloc<_Traits>::_Freeheadnode(std::_Tree_node<std::pair<const _Kty,_Ty>,std::_Default_allocator_traits<_Alloc>::void_pointer> *)'
        with
        [
            _Traits=std::_Tmap_traits<bla::foo,std::string,std::less<bla::foo>,std::allocator<std::pair<const bla::foo,std::string>>,false>,
            _Kty=bla::foo,
            _Ty=std::string,
            _Alloc=std::allocator<std::pair<const bla::foo,std::string>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\xtree(631): note: see reference to function template instantiation 'void std::_Tree_comp_alloc<_Traits>::_Freeheadnode(std::_Tree_node<std::pair<const _Kty,_Ty>,std::_Default_allocator_traits<_Alloc>::void_pointer> *)' being compiled
        with
        [
            _Traits=std::_Tmap_traits<bla::foo,std::string,std::less<bla::foo>,std::allocator<std::pair<const bla::foo,std::string>>,false>,
            _Kty=bla::foo,
            _Ty=std::string,
            _Alloc=std::allocator<std::pair<const bla::foo,std::string>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\xtree(842): note: see reference to class template instantiation 'std::_Tree_comp_alloc<_Traits>' being compiled
        with
        [
            _Traits=std::_Tmap_traits<bla::foo,std::string,std::less<bla::foo>,std::allocator<std::pair<const bla::foo,std::string>>,false>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\map(81): note: see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled
        with
        [
            _Kty=bla::foo,
            _Ty=std::string,
            _Pr=std::less<bla::foo>,
            _Alloc=std::allocator<std::pair<const bla::foo,std::string>>
        ]
C:\Projekte\monalysis\Entwicklung\Quellen\Projekte\scratchpad\main.cpp(212): note: see reference to class template instantiation 'std::map<bla::foo,std::string,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' being compiled
        with
        [
            _Kty=bla::foo,
            _Ty=std::string
        ]
  • Which compiler and operating system are you using? Is it a supported compiler?
    MSVC 2017 (15.6.6); MSVC 19.0.24215.1 (CMake output)
    Not directly supported.

  • Did you use a released version of the library or the version from the develop branch?
    Release 3.1.2

  • If you experience a compilation error: can you compile and run the unit tests?
    Tried but ctest gives error Test not available without configuration. (Missing "-C <config>"?) for every test case. If told how to fix this I'll happily execute the tests.

@theodelrieu
Copy link
Contributor

I dug up a bit, and since there is no std::map conversion in the library (except std::map<string_t, T>, which is basic_json::object_t), the library treats your map as an array.

Thus, it simply iterates on each object, and tries to construct value_type, which is std::pair<Key const, Value>.

I think the library should support std::map (when Key is not basic_json::string_t), that would solve this issue related to Key const not being assignable.
I don't know what would be the best conversion though, having an array of pairs seems reasonable.

As for why the heck does it compile when you put the to/from_json in namespace bla:

Since bla::foo is part of the template arguments of map, IIRC argument-dependent lookup also looks in namespaces associated with template arguments. Which is why the library finds your functions (which should not normally be found, since they're located in the namespace std)

theodelrieu added a commit to theodelrieu/json that referenced this issue May 14, 2018
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

fixes nlohmann#1079
theodelrieu added a commit to theodelrieu/json that referenced this issue May 14, 2018
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

fixes nlohmann#1079
theodelrieu added a commit to theodelrieu/json that referenced this issue May 22, 2018
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

fixes nlohmann#1079
theodelrieu added a commit to theodelrieu/json that referenced this issue May 28, 2018
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

fixes nlohmann#1079
theodelrieu added a commit to theodelrieu/json that referenced this issue May 28, 2018
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

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

Successfully merging a pull request may close this issue.

2 participants