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

map string string fails to compile #176

Closed
matspetter opened this issue Jan 12, 2016 · 7 comments
Closed

map string string fails to compile #176

matspetter opened this issue Jan 12, 2016 · 7 comments
Labels
confirmed kind: bug solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)

Comments

@matspetter
Copy link

I fail to compile this piece of code:

using namespace nlohmann;
using maptype = std::map<std::string, std::string>;

maptype t;
json s=t; // this works
s.get<maptype>(); // this line fails
// if I change to map<string,int> then it compiles
@nlohmann
Copy link
Owner

Just to make sure: in your comment, you mean

// if I change to map<std::string,std::string> then it compiles

and not

// if I change to map<string,int> then it compiles

@matspetter
Copy link
Author

no, I mean that if I change to:

using maptype = std::map<std::string, int>;

then it compiles as it should

@nlohmann
Copy link
Owner

I have not analyzed the bug deeper, but the issue seems not to be type alias. The following code also fails to compile:

#include <json.hpp>

using nlohmann::json;

int main()
{
    std::map<std::string, std::string> t;

    // this works
    json s = t;

    // the fails
    s.get<std::map<std::string, std::string>>();
}

@nlohmann
Copy link
Owner

Same error with a more concise example:

#include <json.hpp>

using nlohmann::json;

int main()
{
    json s = json::object();
    std::map<std::string, std::string> m = s;
}

Error:

In file included from issue176.cpp:1:
In file included from src/json.hpp:41:
In file included from /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:627:
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility:354:15: error: call to constructor of 'std::__1::basic_string<char>' is ambiguous
              second(_VSTD::forward<typename tuple_element<1,
              ^      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/map:630:11: note: in instantiation of function template specialization 'std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> >::pair<std::__1::pair<const std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> > &, void>' requested here
        : __cc(std::forward<_Args>(__args)...) {}
          ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1731:31: note: in instantiation of function template specialization 'std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >::__value_type<std::__1::pair<const std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> > &>' requested here
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                              ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1647:18: note: in instantiation of function template specialization 'std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, void *> >::construct<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, std::__1::pair<const std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> > &>' requested here
            {__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
                 ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1493:14: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, void *> > >::__construct<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, std::__1::pair<const std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> > &>' requested here
            {__construct(__has_construct<allocator_type, _Tp*, _Args...>(),
             ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:1720:20: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, void *> > >::construct<std::__1::__value_type<std::__1::basic_string<char>, std::__1::basic_string<char> >, std::__1::pair<const std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> > &>' requested here
    __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
                   ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:1805:25: note: (skipping 3 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
    __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v));
                        ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/map:904:13: note: in instantiation of function template specialization 'std::__1::map<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >::insert<std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::__value_type<std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> >, std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> >, void *> *, long> > >' requested here
            insert(__f, __l);
            ^
src/json.hpp:2181:20: note: in instantiation of function template specialization 'std::__1::map<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >::map<std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::__value_type<std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> >, std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator> >, void *> *, long> > >' requested here
            return T(m_value.object->begin(), m_value.object->end());
                   ^
src/json.hpp:2463:16: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator>::get_impl<std::__1::map<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >, 0>' requested here
        return get_impl(static_cast<ValueType*>(nullptr));
               ^
src/json.hpp:2603:16: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator>::get<std::__1::map<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >, 0>' requested here
        return get<ValueType>();
               ^
issue176.cpp:8:44: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator>::operator map<std::__1::map<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >, 0>' requested here
    std::map<std::string, std::string> m = s;
                                           ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1326:40: note: candidate constructor
    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
                                       ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1338:5: note: candidate constructor
    basic_string(basic_string&& __str)
    ^
/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:1333:5: note: candidate constructor
    basic_string(const basic_string& __str);
    ^
1 error generated.
make: *** [issue176] Error 1

@nlohmann
Copy link
Owner

This function triggered the error:

/// get an object (explicit)
template <class T, typename
          std::enable_if<
              std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
              std::is_convertible<basic_json_t, typename T::mapped_type>::value
              , int>::type = 0>
T get_impl(T*) const

This function tries to return an object of type T, constructed via T(m_value.object->begin(), m_value.object->end()). So a smaller example for the error is:

#include <json.hpp>

using nlohmann::json;

int main()
{
    json::object_t s;
    std::map<std::string, std::string>(s.begin(), s.end());
}

For the last line's constructor, the documentation states for the iterators:

Input iterators to the initial and final positions in a range. The range used is [first,last), which includes all the elements between first and last, including the element pointed by first but not the element pointed by last.
The function template argument InputIterator shall be an input iterator type that points to elements of a type from which value_type objects can be constructed (in map, value_type is an alias of pair<const key_type, mapped_type>)

This can reduce the example to

#include <json.hpp>

using nlohmann::json;

int main()
{
    json::object_t::value_type s;
    std::map<std::string, std::string>::value_type t(s);
}

@nlohmann
Copy link
Owner

Further reduction:

#include <json.hpp>

using nlohmann::json;

int main()
{
    json s;
    std::string t(s);
}

error:

issue176.cpp:11:17: error: call to constructor of 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') is ambiguous
    std::string t(s);
                ^ ~
include/c++/v1/string:1326:40: note: candidate constructor
    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
                                       ^
include/c++/v1/string:1338:5: note: candidate constructor
    basic_string(basic_string&& __str)
    ^
include/c++/v1/string:1333:5: note: candidate constructor
    basic_string(const basic_string& __str);
    ^
1 error generated.
make: *** [issue176] Error 1

@nlohmann
Copy link
Owner

Found this comment on StackOverflow, quoting cppreference:

Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and user-defined conversion functions, while direct-initialization considers all constructors and implicit conversion sequences.

Indeed, std::string t = s works, whereas std::string t(s) does not.

@nlohmann nlohmann added the solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope) label Feb 16, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed kind: bug solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)
Projects
None yet
Development

No branches or pull requests

2 participants