18#ifndef MOTIV_BUILDER_HPP
19#define MOTIV_BUILDER_HPP
23#define EVAL0(...) __VA_ARGS__
24#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
25#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
26#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
27#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
28#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
34#define MAP_GET_END2() 0, MAP_END
35#define MAP_GET_END1(...) MAP_GET_END2
36#define MAP_GET_END(...) MAP_GET_END1
37#define MAP_NEXT0(test, next, ...) next MAP_OUT
38#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
39#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
41#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
42#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
44#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
45#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
47#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
48#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
53#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
59#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
61#define BUILDER_CHECK(field) check_ ## field();
62#define BUILDER_DREF(field) *field ## _
67#define BUILDER_FIELD(type, name) \
69 std::shared_ptr<type> name ## _; \
70 void check_ ## name() { \
72 throw std::invalid_argument("Field '"#name"'must be set!"); } \
74 Builder * name(type & s) { \
75 name ## _ = std::make_shared<type>(s); \
78 std::shared_ptr<type> name() { \
82#define BUILDER_OPTIONAL_FIELD(type, name) \
84 std::shared_ptr<type> name ## _; \
86 type name() const { return *name ## _; } \
87 Builder * name(type & s) { \
88 name ## _ = std::make_shared<type>(s); \
111#define BUILDER(type, content, ...) \
112class Builder : public builder<type> { \
114 Builder() = default; \
116 MAP(BUILDER_CHECK, __VA_ARGS__) \
117 return {MAP_LIST(BUILDER_DREF, __VA_ARGS__)}; \
125 virtual ~builder() =
default;
135 virtual T build() = 0;