22#ifdef UGMISC_HAVE_CONCEPTS
23template<
typename OStream>
24inline auto& operator<<(OStream& out, Things* things)
25requires std::same_as<OStream, std::ostream> || std::same_as<OStream, std::wostream>
27 return out <<
"<Things>";
30template<
typename OStream>
31inline auto& thingsOutput(OStream& out, Things* things) {
32 return out <<
"<Things>";
35inline std::ostream& operator<<(std::ostream& out, Things* things) {
36 return thingsOutput(out, things);
39inline std::wostream& operator<<(std::wostream& out, Things* things) {
40 return thingsOutput(out, things);
68 static inline const char* defaultWomble(T&);
69 static inline const char* defaultUse(T&, Things*);
70 static inline const char* defaultName(T&);
74 static auto womble(T& w) {
78 return defaultWomble(w);
89 static auto use(T& w, Things* found) {
93 auto getDefault = [&](
auto...args) {
94 return defaultUse(w, args...);
100 static auto name(T& w) {
101 using namespace ugmisc;
104 auto getDefaultName = [&]() {
return defaultName(w); };
105 auto getNameValue = [&]() {
106 return member_value<Name>{}(w)(getDefaultName);
108 auto getNameFunction = member_caller<Name>::fallback(getNameValue)(w);
109 return getNameFunction();
115const char* WombleTraits<T>::defaultWomble(T&) {
117 out <<
"WombleTraits::defaultWomble(" << getTypeName<T>() <<
"&)";
118 return "WombleTraits::defaultWomble()";
122const char* WombleTraits<T>::defaultUse(T&, Things*) {
124 out <<
"WombleTraits::defaultUse(" << getTypeName<T>() <<
"&, Things*)";
125 return "WombleTraits::defaultUse()";
129const char* WombleTraits<T>::defaultName(T&) {
131 out <<
"WombleTraits::defaultName(" << getTypeName<T>() <<
"&)";
132 return "WombleTraits::defaultName()";
137struct CompleteWomble {
138 static constexpr const char *sTypeName =
"CompleteWomble";
140 const char * use(Things* found) {
142 out <<
"CompleteWomble::use(" << found <<
")";
143 return "CompleteWomble::use()";
148 out <<
"CompleteWomble::name()";
149 return "CompleteWomble";
152 const char *womble() {
154 out <<
"CompleteWomble::womble()";
155 return "CompleteWomble::womble()";
161 static constexpr const char *sTypeName =
"EmptyWomble";
165int main(
int,
char**) {
167 auto always = out.always();
168 auto expect = out.expect();
172 CompleteWomble complete;
175 using CompleteTraits = WombleTraits<CompleteWomble>;
176 using EmptyTraits = WombleTraits<EmptyWomble>;
178 always <<
"CompleteTraits::name(complete)\n ";
179 CompleteTraits::name(complete);
181 expect <<
"CompleteWomble::name()"
184 always <<
"CompleteTraits::womble(complete)\n ";
185 CompleteTraits::womble(complete);
187 expect <<
"CompleteWomble::womble()"
190 always <<
"CompleteTraits::use(complete, things)\n ";
191 CompleteTraits::use(complete, things);
193 expect <<
"CompleteWomble::use(" << things <<
")"
196 always <<
"EmptyTraits::name(empty)\n ";
197 EmptyTraits::name(empty);
199 expect <<
"WombleTraits::defaultName(" << getTypeName<EmptyWomble>() <<
"&)"
202 always <<
"EmptyTraits::womble(empty)\n ";
203 EmptyTraits::womble(empty);
205 expect <<
"WombleTraits::defaultWomble(" << getTypeName<EmptyWomble>() <<
"&)"
208 always <<
"EmptyTraits::use(empty, things)\n ";
209 EmptyTraits::use(empty, things);
211 expect <<
"WombleTraits::defaultUse(" << getTypeName<EmptyWomble>() <<
"&, Things*)"
Testing for and using named static and non static members of types.
#define UGMISC_DECL_MEMBER_ACCESS(TNAME, NAME)
static constexpr default_function< F > fallback(F &&f)