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

Support moving from rvalues in std::initializer_list #663

Merged
merged 8 commits into from
Jul 30, 2017

Conversation

himikof
Copy link
Contributor

@himikof himikof commented Jul 23, 2017

This should fix the underlying problem of inefficient list initialization, which has led me to filing #657.

By using a rvalue-aware proxy type inside all uses of std::initializer_list, simple, obvious usages such as

return json {
   {"type", "Polygon"},
   {"coordinates", std::move(coordinates)},
};

should just work without calling json copy constructor even once.

Possible downsides for this solution:

  • It can increase the number of move constructor calls in some situations. I think it is a good trade-off to make, because moving json values should be very cheap (and possibly optimized into nothing).
  • It is, strictly speaking, a breaking interface change, but it is only limited to somehow using an explicitly typed std::initializer_list values, which is not common in C++. All normal usage should remain unaffected (just a bit faster).
  • It is certainly a hack 😃

This commit works around an issue in std::initializer_list design.
By using a detail::json_ref proxy with a mutable value inside,
rvalue-ness of an input to list initializer is remembered and
used later to move from the proxy instead of copying.
std::initializer_list does not own the temporaries created in
its initialization. Therefore, storing it in an independent
stack variable is unsafe.
C++ overload resolution/list initialization rules are hard.
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 0f4978e on himikof:move-construction into 4414f94 on nlohmann:develop.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 0f4978e on himikof:move-construction into 4414f94 on nlohmann:develop.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 897879b on himikof:move-construction into 4414f94 on nlohmann:develop.

On MSVC compiler, temporaries that are constructed during a
list initialization, are sometimes destroyed even before calling
the initializing constructor, instead of at the end of the
containing full-expression. This is clearly non-conforming to
[class.temporary].
As the impact of this bug is silently producing incorrect
JSON values, move eagerly from rvalues to be safe.

See https://stackoverflow.com/questions/24586411
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 93bb712 on himikof:move-construction into 4414f94 on nlohmann:develop.

Copy link
Owner

@nlohmann nlohmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@nlohmann nlohmann self-assigned this Jul 30, 2017
@nlohmann nlohmann added this to the Release 3.0.0 milestone Jul 30, 2017
@nlohmann nlohmann merged commit 80e9584 into nlohmann:develop Jul 30, 2017
@nlohmann
Copy link
Owner

Thanks a lot!

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling aad5521 on himikof:move-construction into 96dd4ff on nlohmann:develop.

nlohmann added a commit that referenced this pull request Jul 30, 2017
@nlohmann
Copy link
Owner

I have some conversion warnings when compiling with GCC with maximal warnings:

$  make pedantic_gcc
/Library/Developer/CommandLineTools/usr/bin/make json_unit CXX=g++ CXXFLAGS="\
		-std=c++11 \
		-Wno-deprecated-declarations \
		-Werror \
		-Wall -Wpedantic -Wextra \
		-Walloca \
		-Warray-bounds=2 \
		-Wcast-qual -Wcast-align \
		-Wchar-subscripts \
		-Wconditionally-supported \
		-Wconversion \
		-Wdate-time \
		-Wdeprecated \
		-Wdisabled-optimization \
		-Wdouble-promotion \
		-Wduplicated-branches \
		-Wduplicated-cond \
		-Weffc++ \
		-Wformat-overflow=2 \
		-Wformat-signedness \
		-Wformat-truncation=2 \
		-Wformat=2 \
		-Wno-ignored-qualifiers \
		-Wimplicit-fallthrough=5 \
		-Wlogical-op \
		-Wmissing-declarations \
		-Wmissing-format-attribute \
		-Wmissing-include-dirs \
		-Wnoexcept \
		-Wnonnull \
		-Wnull-dereference \
		-Wold-style-cast \
		-Woverloaded-virtual \
		-Wparentheses \
		-Wplacement-new=2 \
		-Wredundant-decls \
		-Wreorder \
		-Wrestrict \
		-Wshadow=global \
		-Wshift-overflow=2 \
		-Wsign-conversion \
		-Wsign-promo \
		-Wsized-deallocation \
		-Wstrict-overflow=5 \
		-Wsuggest-attribute=const \
		-Wsuggest-attribute=format \
		-Wsuggest-attribute=noreturn \
		-Wsuggest-attribute=pure \
		-Wsuggest-final-methods \
		-Wsuggest-final-types \
		-Wsuggest-override \
		-Wtrigraphs \
		-Wundef \
		-Wuninitialized -Wunknown-pragmas \
		-Wunused \
		-Wunused-const-variable=2 \
		-Wunused-macros \
		-Wunused-parameter \
		-Wuseless-cast \
		-Wvariadic-macros"
[CXX]   src/unit-constructor1.o
src/unit-constructor1.cpp: In function ‘void ____C_A_T_C_H____T_E_S_T____0()’:
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
             json j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
                                                                                                                                 ^
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:205:129: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:205:129: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
             json j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
                                                                                       ^
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:348:87: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
src/unit-constructor1.cpp:348:87: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:348:87: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:862:75: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(json::array_t())});
                                                                           ^
src/unit-constructor1.cpp:862:75: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:862:75: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:877:76: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(json::object_t())});
                                                                            ^
src/unit-constructor1.cpp:877:76: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:877:76: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:892:73: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json("Hello world")});
                                                                         ^
src/unit-constructor1.cpp:892:73: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:892:73: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:907:64: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(true)});
                                                                ^
src/unit-constructor1.cpp:907:64: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:907:64: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:922:61: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(1)});
                                                             ^
src/unit-constructor1.cpp:922:61: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:922:61: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:937:62: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(1u)});
                                                              ^
src/unit-constructor1.cpp:937:62: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:937:62: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:952:65: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversio]
                     json j(json::initializer_list_t {json(42.23)});
                                                                 ^
src/unit-constructor1.cpp:952:65: error:   for conversion from ‘nlohmann::json {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:952:65: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:1123:50: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
                     json j {std::move(source), {}};
                                                  ^
src/unit-constructor1.cpp:1123:50: error:   for conversion from ‘std::remove_reference<nlohmann::basic_json<>&>::type {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:1123:50: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:1129:55: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
                     json j {{"key", std::move(source)}};
                                                       ^
src/unit-constructor1.cpp:1129:55: error:   for conversion from ‘std::remove_reference<nlohmann::basic_json<>&>::type {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:1129:55: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:1135:52: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
                     json j = {std::move(source), {}};
                                                    ^
src/unit-constructor1.cpp:1135:52: error:   for conversion from ‘std::remove_reference<nlohmann::basic_json<>&>::type {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:1135:52: note:   because conversion sequence for the argument is better
src/unit-constructor1.cpp:1141:57: error: choosing ‘nlohmann::detail::json_ref<BasicJsonType>::json_ref(nlohmann::detail::json_ref<BasicJsonType>::value_type&&) [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::json_ref<BasicJsonType>::value_type = nlohmann::basic_json<>]’ over ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::operator ValueType() const [with ValueType = nlohmann::detail::json_ref<nlohmann::basic_json<> >; typename std::enable_if<(((! std::is_pointer<_Ptr>::value) && (! std::is_same<ValueType, typename StringType::value_type>::value)) && (! std::is_same<ValueType, std::initializer_list<typename StringType::value_type> >::value)), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’ [-Werror=conversion]
                     json j = {{"key", std::move(source)}};
                                                         ^
src/unit-constructor1.cpp:1141:57: error:   for conversion from ‘std::remove_reference<nlohmann::basic_json<>&>::type {aka nlohmann::basic_json<>}’ to ‘nlohmann::detail::json_ref<nlohmann::basic_json<> >’ [-Werror=conversion]
src/unit-constructor1.cpp:1141:57: note:   because conversion sequence for the argument is better
cc1plus: all warnings being treated as errors
make[2]: *** [src/unit-constructor1.o] Error 1
make[1]: *** [json_unit] Error 2
make: *** [pedantic_gcc] Error 2

Any ideas on this?

@nlohmann
Copy link
Owner

Furthermore, there is a Weffc++ warning that json_ref has pointer members, but no copy constructor or assignment operator.

@himikof
Copy link
Contributor Author

himikof commented Jul 30, 2017

As for the conversion warnings, it seems to be an unwanted (but harmless) interplay with basic_json::operator ValueType() const, which is not supposed to be used with json_ref. So, SFINAE-blacklisting ValueType == json_ref there should get rid of this warning.

As for constructors, json_ref should only be movable, and default move constructor is fine on a conforming C++11 compiler. So, adding json_ref(json_ref &&) = default; should be enough.

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

Successfully merging this pull request may close these issues.

None yet

3 participants