Skip to content

implicit conversion failure #2128

Description

@gcerretani
  • What is the issue you have?
    Strange behavior of implicit conversion

  • Please describe the steps to reproduce the issue. Can you provide a small but working code example?

#include <cstdlib>
#include <string>
#include <list>
#include <boost/range/algorithm/transform.hpp>
#include <nlohmann/json.hpp>
#include <type_traits>

struct my_struct {
	enum class names { UNKNOWN, FOO, BAR };
};

NLOHMANN_JSON_SERIALIZE_ENUM(my_struct::names, {
	{ my_struct::names::UNKNOWN, 			nullptr },
	{ my_struct::names::FOO, 				"FOO" },
	{ my_struct::names::BAR, 				"BAR" }
})

template <typename T>
struct json_data_format {

	json_data_format()
		: _name{ names::UNKNOWN } {
	}

	template <typename... Args>
	static json_data_format marshal(Args&& ...args) {
		return nlohmann::json::parse(std::forward<Args>(args)...);
	}

	nlohmann::json::string_t unmarshal() const {
		return nlohmann::json(*this).dump();
	}

	~json_data_format() = default;
	json_data_format(const json_data_format&) = default;
	json_data_format(json_data_format&&) = default;
	json_data_format& operator=(const json_data_format&) = default;
	json_data_format& operator=(json_data_format&&) = default;

	auto get_name() const noexcept { return _name; }

	friend void from_json(const nlohmann::json& j, json_data_format& e) {
		const auto get_if_not_null = [&j](const char* key, auto& value) {
			try {
				const auto j_value = j.at(key);
				if (!j_value.is_null())
					j_value.get_to(value);
			}
			catch (const nlohmann::json::out_of_range&) {}
		};
		get_if_not_null(json_data_format::key_name, e._name);
	}

	friend void to_json(nlohmann::json& j, const json_data_format& e) {
		const auto set = [&j](const char* key, const auto& value) {
			j.update(nlohmann::json::object({ { key, value } }));
		};
		set(json_data_format::key_name, e._name);
	}

	static constexpr const char* key_name = "name";

private:
	using names = typename T::names;
	names _name;
};

using namespace std::string_literals;

int main() {
	auto j = nlohmann::json::parse(R"([ { "name" : "FOO" }, { "name" : "BAR" } ])");
	std::list<my_struct::names> _args_list;
	boost::transform(j, std::back_inserter(_args_list), [](const nlohmann::json& element) {
		const json_data_format<my_struct> format = element; // implicit conversion
		return format.get_name();
	});
	return EXIT_SUCCESS;
}
  • What is the expected behavior?
    The json is correctly parsed.

  • And what is the actual behavior instead?
    The parse fails because the lambda get_if_not_null is called with nullptr as first argument (the const char* key). The code works correctly if the implicit conversion is replaced by an explicit conversion with auto format = element.get<json_data_format<my_struct>>();

  • Which compiler and operating system are you using? Is it a supported compiler?
    Microsoft Visual C++ 2015 / Build Tools 14.0.25431.01, currently supported. I've tried also with GCC 7 and everything seems to work as expected.

  • Did you use a released version of the library or the version from the develop branch?
    v3.7.3

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind: bugplatform: visual studiorelated to MSVCstate: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions