getml / reflect-cpp

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML / msgpack.org[C++20]
https://getml.github.io/reflect-cpp/
MIT License
775 stars 61 forks source link

C++17 #7

Open thknx opened 8 months ago

thknx commented 8 months ago

Hi,

Is there a way to use reflect-cpp with projects that only c++17 compatible?

liuzicheng1987 commented 8 months ago

This is a bit tricky...we use C++ concepts quite a bit, which is C++ 20 feature. But maybe we can find a workaround using Macros. You are not the first one to request this, to be honest.

muddessir commented 8 months ago

It would be amazing if it can be used in c++17/c++14 projects. (And the option of disabling exceptions)

Thank you.

liuzicheng1987 commented 8 months ago

As far as the exceptions are concerned, we already have that:

https://github.com/getml/reflect-cpp/blob/main/docs/result.md

liuzicheng1987 commented 8 months ago

Here is the next problem: The way we pass strings as a template parameter is a C++ 20 feature:

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf

As explained in this proposal, if we did this in C++ 17, we would always have to explicitly pass the string length as well. So instead of:

rfl::Field<std::string, "firstName">

we would have to write

rfl::Field<std::string, "firstName", 9>

which is obviously less elegant. If someone can find a workaround for that, I am very open to ideas.

Pennywise007 commented 7 months ago

@liuzicheng1987 I am not sure that there will be an elegant solution for C++17, as I understand one of the main features of your library is that macros are not required, I would say to make it compatible with C++17 adding simple macros just to add text will be fine. I would recommend you to check this, this solution allows add text as a template argument in C++17 without providing an extra length argument. I understand that all this decltype("text"_something) is not elegant, but I would say just create a simple macro, sth like:

#if __cplusplus >= 202002L
#define Name(text) decltype(text##_something)
#else
#define Name(text) text
#endif

And declare field like(only necessary for C++17, but for C++20 also will work): rfl::Field<std::string, Name("firstName")>

The other problem is that std::is_constructible will be false in C++17 for this case:

struct T {
   int a;
};
static_assert(std::is_constructible_v<T, int>); // false

But it is easy to fix. I am not completely sure but it looks like the rest code should work without big changes in C++17.