Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
member.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#pragma once
3
4#include <ase/parameter.hh>
5
6namespace Ase {
7
9 static constexpr uint64_t READABLE = 1, WRITABLE = 2, STORAGE = 4, GUI = 8,
10 RW_STORAGE = READABLE + WRITABLE + STORAGE, FLAGS_DEFAULT = RW_STORAGE + GUI;
11 uint64_t flags = FLAGS_DEFAULT;
12 StringS infos;
13 bool is_unset () const { return flags == FLAGS_DEFAULT && infos.empty(); }
14 bool operator== (const MemberDetails &m) const { return flags == m.flags && infos == m.infos; }
15 String
16 info (const String &key) const
17 {
18 for (const auto &kv : infos)
19 if (kv.size() > key.size() && kv[key.size()] == '=' &&
20 kv.compare (0, key.size(), key) == 0)
21 return kv.substr (key.size() + 1);
22 return "";
23 }
24 const MemberDetails&
25 assign1 (const MemberDetails *newmeta)
26 { // assign once only
27 MemberDetails &old_meta = *this;
28 if (newmeta) {
29 ASE_ASSERT (old_meta.is_unset() || old_meta == *newmeta);
30 old_meta = *newmeta;
31 }
32 return *this;
33 }
34};
35
36namespace Lib { // Implementation internals
38template<typename F> struct FunctionTraits;
39template<typename R, typename ...Args> struct FunctionTraits<R (Args...)> {
40 using ReturnType = R;
41 using Arguments = std::tuple<Args...>;
42};
44template<typename C, typename R, typename ...Args>
45struct FunctionTraits<R (C::*) (Args...)> : FunctionTraits<R (C&, Args...)> {
46 using ClassType = C;
47 using ReturnType = R;
48};
50template<typename C, typename R, typename ...Args>
51struct FunctionTraits<R (C::*) (Args...) const> : FunctionTraits<R (const C&, Args...)> {
52 using ClassType = C;
53 using ReturnType = R;
54 using Arguments = std::tuple<Args...>;
55};
57template<auto Handler>
59 using FuncType = typename std::decay<decltype (Handler)>::type;
60 using Arguments = typename FunctionTraits<FuncType>::Arguments;
61 using ClassType = typename FunctionTraits<decltype (Handler)>::ClassType;
62 using ReturnType = typename FunctionTraits<decltype (Handler)>::ReturnType;
63};
65template<class C, class M> C*
66host_member_offset (ptrdiff_t *hmoffsetp, const M *member, C *host)
67{
68 if (host) {
69 const ptrdiff_t member_offset = ptrdiff_t (member) - ptrdiff_t (host);
70 ASE_ASSERT (*hmoffsetp == -1 || *hmoffsetp == member_offset);
71 *hmoffsetp = member_offset;
72 } else {
73 ASE_ASSERT (*hmoffsetp >= 0);
74 const ptrdiff_t host_offset = ptrdiff_t (member) - *hmoffsetp;
75 host = reinterpret_cast<C*> (host_offset);
76 }
77 return host;
78}
79
80bool kvpairs_assign (StringS &kvs, const String &key_value_pair);
81
82} // Lib
83
85template<auto getter, auto setter = nullptr>
86class Member {
87public:
89 using Class = typename GetterTraits::ClassType;
91 // Recommended: static_assert (std::is_same_v<typename GetterTraits::FuncType, G (Class::*) () const>);
96 // Recommended: static_assert (std::is_same_v<typename SetterTraits::FuncType, void (Class::*) (const T&)>);
97 static_assert (std::is_convertible_v<T, G>);
99 static Class* host_ (const Member *m, Class *o = nullptr) { static ptrdiff_t d = -1; return Lib::host_member_offset (&d, m, o); }
101 static const MemberDetails& meta_ (const MemberDetails *n = nullptr) { static MemberDetails m; return m.assign1 (n); }
102public:
103 Member (Class *o, const String &n = "", const StringS &s = {}) : Member (o, n, {}, {}, MemberDetails::FLAGS_DEFAULT, s, false) {}
104 Member (Class *o, const String &n, const ParamInitialVal &iv, const StringS &s = {}) : Member (o, n, iv, {}, MemberDetails::FLAGS_DEFAULT, s) {}
105 Member (Class *o, const String &n, const ParamInitialVal &iv, const ParamExtraVals &ev, const StringS &s = {}) : Member (o, n, iv, ev, MemberDetails::FLAGS_DEFAULT, s) {}
106 Member (Class *o, const String &n, const ParamExtraVals &ev, const StringS &s = {}) : Member (o, n, {}, ev, MemberDetails::FLAGS_DEFAULT, s, false) {}
107 Member (Class *o, const String &n, const ParamInitialVal &iv, const ParamExtraVals &ev, uint64_t hints, const StringS &s = {}, bool init = true)
108 {
109 ASE_ASSERT (o);
110 MemberDetails meta;
111 meta.infos = s;
112 if (!n.empty())
113 Lib::kvpairs_assign (meta.infos, "ident=" + n);
114 meta_ (&meta);
115 host_ (this, o);
116 constexpr bool has_register_parameter = requires (Class *o, Member *m) { o->_register_parameter (o, m, ev); };
117 if constexpr (has_register_parameter)
118 o->_register_parameter (o, this, ev);
119 if (!init) return;
120 std::visit ([&] (auto &&ival) {
121 using T = std::decay_t<decltype (ival)>;
123 set (ival);
124 else
125 ASE_ASSERT_RETURN (!"initializing");
126 }, iv);
127 }
128 using value_type = T;
129 T get () const { return (host_ (this)->*getter) (); }
130 bool set (const T &value)
131 {
132 if constexpr (!std::is_same_v<S,void>)
133 return !!(host_ (this)->*setter) (std::forward<const T&> (value));
134 else
135 return (host_ (this)->*setter) (std::forward<const T&> (value)), true;
136 }
137 T operator() () const { return get(); }
138 bool operator() (const T &value) { return set (std::forward<const T&> (value)); }
139 operator T () const { return get (); }
140 bool operator= (const T &value) { return set (std::forward<const T&> (value)); }
141 void notify () const { host_ (this)->emit_notify (info ("ident")); }
142 static constexpr bool is_unique_per_member = true; // typeid will uniquely identify a member, due to <setter> arg
143 static uint64_t hints () { return meta_().flags; }
144 static const StringS& infos () { return meta_().infos; }
145 static String info (const String &key) { return meta_().info (key); }
146};
147
148} // Ase
Implement C++ member field API with a 0-sized class from setter and getter, maybe combined with [[no_...
Definition member.hh:86
static Class * host_(const Member *m, Class *o=nullptr)
Resolve (or assign) host->Member distance (may be 0).
Definition member.hh:99
static const MemberDetails & meta_(const MemberDetails *n=nullptr)
Retrieve or assign property meta infos.
Definition member.hh:101
#define ASE_ASSERT(expr)
Issue an assertion warning if expr evaluates to false.
Definition cxxaux.hh:91
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:82
T empty(T... args)
C * host_member_offset(ptrdiff_t *hmoffsetp, const M *member, C *host)
Resolve (or assign) host->Member offset distance (may be 0).
Definition member.hh:66
The Anklang C++ API namespace.
Definition api.hh:9
std::vector< String > StringS
Convenience alias for a std::vector<std::string>.
Definition cxxaux.hh:36
std::variant< bool, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double, const char *, std::string > ParamInitialVal
Initial value for parameters.
Definition parameter.hh:18
std::string String
Convenience alias for std::string.
Definition cxxaux.hh:35
T size(T... args)
typedef uint64_t
Match function pointers.
Definition member.hh:38
Member function traits.
Definition member.hh:58
T substr(T... args)
T visit(T... args)