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

adl_serializer and CRTP #680

Closed
stevefan1999-personal opened this issue Aug 8, 2017 · 3 comments
Closed

adl_serializer and CRTP #680

stevefan1999-personal opened this issue Aug 8, 2017 · 3 comments
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@stevefan1999-personal
Copy link

stevefan1999-personal commented Aug 8, 2017

Because I really hate defining to_json/from_json by using the infamous ADL trick (I come from a C#/Java background so the fame of ADL depends), I decided to make the OOP-way-of-serialization shim of my own

I was having some progress, the following code demonstrated is a complete valid and legit code:

IJsonSerializable.hpp:

template<class T>
struct IJsonSerializable {
	using self_t = IJsonSerializable<T>;

	constexpr void to_json(json &j) const {
		auto self = const_cast<self_t *>(this);
		static_cast<T *>(self)->to_json(j);
	}

	constexpr void from_json(json &j) const {
		auto self = const_cast<self_t *>(this);
		static_cast<T *>(self)->from_json(j);
	}
};

template <class T>
constexpr void to_json(json &j, const IJsonSerializable<T> *value) {
	value->to_json(j);
}

template <class T>
constexpr void from_json(const json &j, IJsonSerializable<T> *value) {
	auto _j = const_cast<json &>(j);
	value->from_json(_j);
}

template <class T>
constexpr void to_json(json &j, const IJsonSerializable<T> &value) {
	value.to_json(j);
}

template <class T>
constexpr void from_json(const json &j, IJsonSerializable<T> &value) {
	auto _j = const_cast<json &>(j);
	value.from_json(_j);
}

Vector3.hpp:

#include "IJsonSerializable.h"

struct Vector3 : public IJsonSerializable<Vector3> {
	float x, y, z;

public:
	void to_json(json &j)  {
		j = { 
			{ "x", x }, 
			{ "y", y }, 
			{ "z", z} 
		};
	}

	void from_json(json &j) {
		x = j["x"];
		y = j["y"];
		z = j["z"];
	}
};

This works pretty much fine for me, but is there any way to rewrite it in the following form?

namespace nlohmann {
	template <class T>
	struct adl_serializer<IJsonSerializable<T>> { // not working, should I insert SFINAE here?
		using self_t = IJsonSerializable<T>;

		constexpr void to_json(json &j, const self_t *value) {
			value->to_json(j);
		}

		constexpr void from_json(const json &j, self_t *value) {
			auto _j = const_cast<json &>(j);
			value->from_json(_j);
		}

		constexpr void to_json(json &j, const self_t &value) {
			value.to_json(j);
		}

		constexpr void from_json(const json &j, self_t &value) {
			auto _j = const_cast<json &>(j);
			value.from_json(_j);
		}
	};
}

I group all my other serializers into namespace nlohmann just to keep it away from polluting my global namespace without creating another namespace of my own.

@theodelrieu
Copy link
Contributor

theodelrieu commented Aug 8, 2017

I'll take a look once I arrive to work, what if you replace self_t* with a reference?

We do not support pointers in from/to_json at the moment.

EDIT: also you must declare adl_serializer methods as static, it will not work otherwise.

@theodelrieu
Copy link
Contributor

Hi, just checking back, the code works on my laptop when adding static in front of both methods.

By the way, you can remove both overloads that take self_t *, they will never be called by the library.

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Aug 12, 2017
@nlohmann
Copy link
Owner

Can I close this issue?

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

No branches or pull requests

3 participants