Classdesc 3.44
RESTProcess_epilogue.h
1/*
2 @copyright Russell Standish 2019
3 @author Russell Standish
4 This file is part of Classdesc
5
6 Open source licensed under the MIT license. See LICENSE for details.
7*/
8#ifndef CLASSDESC_RESTPROCESS_EPILOGUE_H
9#define CLASSDESC_RESTPROCESS_EPILOGUE_H
10#include "RESTProcess_base.h"
11#include "signature.h"
12#include "multiArray.h"
13#include "polyPackBase.h"
14#include "polyRESTProcess.h"
15#include "RESTProcess-allCDs.h"
16
17namespace classdesc_access
18{
19 namespace classdesc=cd;
20
21 template <class T>
22 struct access_RESTProcess<cd::Exclude<T>>: public cd::NullDescriptor<cd::RESTProcess_t> {};
23
24 template <>
25 struct access_RESTProcess<cd::string>
26 {
27 template <class U>
28 void operator()(cd::RESTProcess_t& repo, const std::string& d, U& a)
29 {repo.add(d, new cd::RESTProcessObject<U>(a));}
30 };
31
32 template <class F, class S>
33 struct access_RESTProcess<std::pair<F,S>>
34 {
35 template <class U>
36 void operator()(cd::RESTProcess_t& repo, const std::string& d, U& a)
37 {
38 RESTProcess(repo,d+".first", a.first);
39 RESTProcess(repo,d+".second", a.second);
40 }
41 };
42
43 template <>
44 struct access_RESTProcess<cd::PolyPackBase>:
45 public cd::NullDescriptor<cd::RESTProcess_t> {};
46
47 template <class T>
48 struct access_RESTProcess<cd::PolyPack<T>>:
49 public cd::NullDescriptor<cd::RESTProcess_t> {};
50
51 template <class T>
52 struct access_RESTProcess<T, cd::void_t<typename std::iterator_traits<T>::value_type>>:
53 public cd::NullDescriptor<cd::RESTProcess_t> {};
54}
55
56namespace classdesc
57{
58 template <class T>
59 std::vector<Signature> RESTProcessObject<T>::signature() const
60 {
61 auto tn=typeName<T>();
62 return std::vector<Signature>{{tn,{}},{tn,{tn}}};
63 }
64
65 template <class T>
66 std::vector<Signature> RESTProcessPtr<T>::signature() const
67 {
68 auto tn=typeName<typename T::element_type>();
69 return {{tn,{}},{tn,{tn}}};
70 }
71
72 template <class T>
73 std::vector<Signature> RESTProcessWeakPtr<T>::signature() const
74 {
75 auto tn=typeName<T>();
76 return {{tn,{}},{tn,{tn}}};
77 }
78
79 template <class T>
80 std::vector<Signature> RESTProcessSequence<T>::signature() const
81 {
82 auto tn=typeName<T>();
83 return {{tn,{}},{tn,{tn}}};
84 }
85
86 template <class T>
87 std::vector<Signature> RESTProcessAssociativeContainer<T>::signature() const
88 {
89 auto tn=typeName<T>();
90 return {{tn,{}},{tn,{tn}}};
91 }
92
93 template <class E>
94 std::vector<Signature> RESTProcessEnum<E>::signature() const
95 {
96 return {{"std::string",{}},{"std::string",{"std::string"}}};
97 }
98
99 template <class E>
100 std::vector<Signature> EnumerateEnumerators<E>::signature() const
101 {
102 return {{"vector<string>",{}}};
103 }
104
105 template <class T>
107 rlist(T& obj)
108 {
109 RESTProcess_t map;
110 obj.RESTProcess(map,"");
111 return map;
112 }
113
114 template <class T>
116 rlist(T& obj)
117 {
118 RESTProcess_t map;
119 RESTProcess(map,"",obj);
120 return map;
121 }
122
123 template <class T>
125 {return rlist(obj);}
126
128
129 template <class T>
131 RESTProcess_t map;
132 map.emplace(".@elem", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessSequence<T>::elem)));
133 map.emplace(".@elemNoThrow", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessSequence<T>::elemNoThrow)));
134 map.emplace(".@erase", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessSequence<T>::eraseElem)));
135 map.emplace(".@insert", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessSequence<T>::pushBack)));
136 map.emplace(".@size", makeRESTProcessFunction(functional::bindMethod(obj,&T::size)));
137 return map;
138 }
139
140 template <class T>
142 RESTProcess_t map;
143 // duplicates here for backward compatibility
144 map.emplace(".@elem", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessAssociativeContainer<T>::elem)));
145 map.emplace(".@elemNoThrow", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessAssociativeContainer<T>::elem)));
146 map.emplace(".@insert", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessAssociativeContainer<T>::elem)));
147 map.emplace(".@erase", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessAssociativeContainer<T>::erase)));
148 map.emplace(".@size", makeRESTProcessFunction(functional::bindMethod(obj,&T::size)));
149 map.emplace(".@keys", makeRESTProcessFunction(functional::bindMethod(*this,&RESTProcessAssociativeContainer<T>::keys)));
150 return map;
151 }
152
153 template <class T>
154 std::string RESTProcessObject<T>::type() const {return typeName<T>();}
155
156
157 template <class F, int N=functional::Arity<F>::value >
158 struct Args: public std::vector<string>
159 {
160 Args(): std::vector<string>(Args<F,N-1>()) {
161 push_back(typeName<typename functional::Arg<F,N>::type>());
162 }
163 };
164
165 template <class F> struct Args<F,0>: public std::vector<string> {};
166
167
168 template <class F>
170 {
171 return {typeName<typename functional::Return<F>::T>(), Args<F>()};
172 }
173
175 template <class T>
177 RESTProcess(RESTProcess_t& r, const string& d, T& a) {RESTProcessp(r,d,a);}
178
179 template <class T>
180 typename enable_if<is_classdescGenerated<T>, void>::T
181 RESTProcessp(RESTProcess_t& repo, string d, T& obj)
182 {
184 if (!is_excluded<T>::value) repo.add(d, new RESTProcessObject<T>(obj));
185 }
186
187 inline RPPtr RESTProcessOverloadedFunction::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
188 {
189 if (overloadedFunctions.empty()) return std::make_shared<RESTProcessVoid>();
190 auto bestOverload=overloadedFunctions.front();
191 auto bestScore=RESTProcessFunctionBase::maxMatchScore;
192 int bestCount=0;
193 for (auto& i: overloadedFunctions)
194 {
195 auto score=i->matchScore(arguments);
196 if (score<bestScore)
197 {
198 bestScore=score;
199 bestOverload=i;
200 bestCount=1;
201 }
202 else if (score==bestScore)
203 ++bestCount;
204 }
205 if (bestOverload->matchScore(arguments) >=
206 RESTProcessFunctionBase::maxMatchScore)
207 throw std::runtime_error("No suitable matching overload found");
208 if (bestCount>1) // ambiguous overload detection
209 throw std::runtime_error("Ambiguous resolution of overloaded function");
210 return bestOverload->process(remainder, arguments);
211 }
212
213 template <class T>
214 RPPtr sequenceProcess(T& obj, const string& remainder, const REST_PROCESS_BUFFER& arguments)
215 {
216 if (remainder.empty())
217 {
218 switch (arguments.type())
219 {
220 case RESTProcessType::null: break;
221 case RESTProcessType::array:
222 {
223 auto& arr=arguments.array();
224 if (!arr.empty()) convert(obj, REST_PROCESS_BUFFER(arr[0]));
225 break;
226 }
227 default:
228 convert(obj, arguments);
229 break;
230 }
231 return makeRESTProcessRef(obj);
232 }
233 else if (startsWith(remainder,".@size"))
234 return makeRESTProcessValueObject(obj.size());
235 return RESTProcess_t(obj).process(remainder,arguments); // treat as an object, not container
236 }
237
238 template <class T, bool isConst> struct IteratorSelector;
239 template <class T> struct IteratorSelector<T, true>
240 {
241 using iterator=typename T::const_iterator;
242 };
243 template <class T> struct IteratorSelector<T, false>
244 {
245 using iterator=typename T::iterator;
246 };
247
248
249 template <class T> std::tuple<typename IteratorSelector<T,is_const<T>::value>::iterator, string::size_type>
250 elemImpl(T& obj, const string& remainder, const REST_PROCESS_BUFFER& arguments)
251 {
252 // extract idx
253 assert(remainder.length()>2);
254 auto idxStart=remainder.find('.',1);
255 if (idxStart==string::npos)
256 throw std::runtime_error("no index");
257 auto idxEnd=remainder.find('.', idxStart+1);
258 if (idxEnd==string::npos) idxEnd=remainder.length();
259 size_t idx=stoi(remainder.substr(idxStart+1, idxEnd));
260 if (idx>=obj.size())
261 {
262 // @elemNoThrow doesn't throw out of bounds error, but may throw invalid index
263 if (startsWith(remainder,".@elemNoThrow"))
264 return {obj.end(),string::npos};
265 throw std::runtime_error("idx out of bounds");
266 }
267 auto i=obj.begin();
268 std::advance(i, idx);
269 return {i,idxEnd};
270 }
271
272 template <class T> RPPtr RESTProcessSequence<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
273 {
274 if (startsWith(remainder,".@elem"))
275 {
276 auto [i, idxEnd]=elemImpl(obj,remainder,arguments);
277 if (i==obj.end()) return std::make_shared<RESTProcessVoid>();
278 return mapAndProcess(remainder.substr(idxEnd), arguments, *i);
279 }
280 if (startsWith(remainder,".@insert"))
281 {
282 insert(obj, arguments);
283 return makeRESTProcessRef(obj);
284 }
285 if (startsWith(remainder,".@erase"))
286 {
287 erase(obj, arguments);
288 return makeRESTProcessRef(obj);
289 }
290 return sequenceProcess(obj,remainder,arguments);
291 }
292
293 template <class T> RPPtr RESTProcessMultiArray<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
294 {
295 if (startsWith(remainder,".@elem"))
296 {
297 auto [i, idxEnd]=elemImpl(actual,remainder,arguments);
298 if (i==actual.end()) return std::make_shared<RESTProcessVoid>();
299 auto r=mapAndProcess(remainder.substr(idxEnd), arguments, *i);
300 if (idxEnd==remainder.length() && T::rank>1)
301 // create a copy of the MultiArray iterator before it goes out of scope
302 return copyMultiArrayIterator(*i);
303 return r;
304 }
305 return sequenceProcess(actual,remainder,arguments);
306 }
307
308 template <class T>
309 RPPtr RESTProcessAssociativeContainer<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
310 {
311 if (remainder.empty())
312 switch (arguments.type())
313 {
314 case RESTProcessType::null: break;
315 case RESTProcessType::array:
316 {
317 auto& arr=arguments.array();
318 if (!arr.empty()) convert(obj, REST_PROCESS_BUFFER(arr[0]));
319 break;
320 }
321 default:
322 convert(obj, arguments);
323 break;
324 }
325 else if (startsWith(remainder,".@elem"))
326 {
327 // extract key
328 auto keyStart=find(remainder.begin()+1, remainder.end(), '.');
329 if (keyStart!=remainder.end())
330 {
331 ++keyStart;
332 auto keyEnd=keyStart;
333 typename T::key_type key;
334 if (strchr("\"'{[",*keyStart)) // JSON leadin
335 {
336 json_pack_t jsonKey;
337 read_range(keyEnd,remainder.end(),static_cast<json5_parser::mValue&>(jsonKey));
338 jsonKey>>key;
339 }
340 else
341 {
342 keyEnd=find(keyStart, remainder.end(), '.');
343 assignRawStringToKey(key, std::string(keyStart, keyEnd));
344 }
345
346 string tail(keyEnd,remainder.end());
347 if (tail.empty() && arguments.type()!=RESTProcessType::null)
348 assignElem(obj, key, arguments);
349 auto i=obj.find(key);
350 if (i==obj.end())
351 {
352 if (startsWith(remainder,".@elemNoThrow"))
353 return mapAndProcessDummy<typename T::value_type>(tail, arguments);
354 else
355 throw std::runtime_error("key "+std::string(keyStart, keyEnd)+" not found");
356 }
357 else if (tail.empty())
358 return makeRESTProcessValueObject(elem_of(i));
359 auto eoi=elem_of(i);
360 return mapAndProcess(tail, arguments, eoi);
361 }
362 }
363 else if (startsWith(remainder,".@insert"))
364 RPAC_insert(obj,arguments);
365 else if (startsWith(remainder,".@erase"))
366 RPAC_erase(obj,arguments);
367 else if (startsWith(remainder,".@size"))
368 return makeRESTProcessValueObject(obj.size());
369 else if (startsWith(remainder,".@keys"))
370 {
371 std::vector<typename T::key_type> keys;
372 for (auto& i: obj)
373 keys.push_back(keyOf(i));
374 return makeRESTProcessValueObject(std::move(keys));
375 }
376 else
377 return RESTProcess_t(obj).process(remainder,arguments); // treat as an object, not container
378 return std::make_shared<RESTProcessAssociativeContainer>(obj);
379 }
380
381 template <class T>
382 RPPtr RESTProcessPtr<T>::process(const string& remainder, const REST_PROCESS_BUFFER& arguments)
383 {
384 if (ptr)
385 return rProcess(*ptr, remainder, arguments);
386 else
387 return std::make_shared<RESTProcessVoid>();
388 }
389
390 template <class E>
391 RPPtr EnumerateEnumerators<E>::process
392 (const string& remainder, const REST_PROCESS_BUFFER& arguments)
393 {
394 auto& enumerators=enum_keys<E>();
395 return makeRESTProcessValueObject(std::vector<string>(enumerators.sbegin(), enumerators.send()));
396 }
397
398
399 template <class T>
401 (const string& remainder, const REST_PROCESS_BUFFER& arguments)
402 {
403 if (auto p=ptr.lock())
404 return rProcess(*p, remainder, arguments);
405 else
406 return std::make_shared<RESTProcessVoid>();
407 }
408
409 inline RPPtr RESTProcess_t::process(const std::string& query, const REST_PROCESS_BUFFER& jin)
410 {
411 string cmd=query;
412
413 if (cmd=="@enum.@list")
414 {
415 std::vector<string> enums;
416 for (auto& i: *this)
417 if (i.first.find("@enum")==0)
418 enums.push_back(i.first.substr(6));
419 return makeRESTProcessValueObject(std::move(enums));
420 }
421
422 for (auto cmdEnd=query.length(); ;
423 cmdEnd=cmd.rfind('.'), cmd=cmd.substr(0,cmdEnd))
424 {
425 if (cmdEnd==string::npos)
426 {
427 cmdEnd=0;
428 cmd="";
429 }
430 auto tail=query.substr(cmdEnd);
431 switch (count(cmd))
432 {
433 case 0:
434 if (cmdEnd)
435 continue; // try next split
436 else
437 throw std::runtime_error("Command not found: "+query);
438 case 1: // simple object or non overloaded function
439 {
440 auto r=find(cmd);
441 if (tail==".@signature")
442 return makeRESTProcessValueObject(r->second->signature());
443 else if (tail==".@list")
444 {
445 auto map=r->second->list();
446 std::vector<string> array;
447 for (auto& i:map)
448 if (!i.first.empty())
449 array.emplace_back(i.first);
450 return makeRESTProcessValueObject(std::move(array));
451 }
452 else if (tail==".@type")
453 return makeRESTProcessValueObject(r->second->type());
454 else if (cmdEnd || dynamic_cast<RESTProcessWrapperBase*>(r->second.get()))
455 return r->second->process(tail, jin);
456 else
457 throw std::runtime_error("Command not found: "+query);
458 }
459 default:
460 {
461 auto r=equal_range(cmd);
462 if (tail==".@signature")
463 {
464 std::vector<Signature> array;
465 for (; r.first!=r.second; ++r.first)
466 {
467 auto sig=r.first->second->signature();
468 array.insert(array.end(), sig.begin(), sig.end());
469 }
470 return makeRESTProcessValueObject(std::move(array));
471 }
472 // sort function overloads by best match
473 auto cmp=[&](RESTProcessFunctionBase*x, RESTProcessFunctionBase*y)
474 {return x->matchScore(jin)<y->matchScore(jin);};
475 std::set<RESTProcessFunctionBase*, decltype(cmp)> sortedOverloads{cmp};
476 for (auto i=r.first; i!=r.second; ++i)
477 if (auto j=dynamic_cast<RESTProcessFunctionBase*>(i->second.get()))
478 sortedOverloads.insert(j);
479 auto& bestOverload=*sortedOverloads.begin();
480 if (bestOverload->matchScore(jin) >=
481 RESTProcessFunctionBase::maxMatchScore)
482 throw std::runtime_error("No suitable matching overload found");
483 if (sortedOverloads.size()>1)
484 { // ambiguous overload detection
485 auto i=sortedOverloads.begin(); i++;
486 if ((*i)->matchScore(jin)==bestOverload->matchScore(jin))
487 throw std::runtime_error("Ambiguous resolution of overloaded function");
488 }
489 if (tail==".@list")
490 {
491 auto map=bestOverload->list();
492 std::vector<std::string> list;
493 for (auto& i: map)
494 if (!i.first.empty())
495 list.push_back(i.first);
496 return makeRESTProcessValueObject(list);
497 }
498 if (tail==".@type")
499 return makeRESTProcessValueObject(bestOverload->type());
500 return bestOverload->process(tail, jin);
501 }
502 }
503 }
504 }
505
506 template <class T>
507 RPPtr mapAndProcess(const string& query, const REST_PROCESS_BUFFER& arguments, T& a)
508 {
510 if (query.empty())
511 {
512 auto i=map.find("");
513 if (i!=map.end())
514 return i->second->process("",arguments);
515 else
516 return {};
517 }
518 return map.process(query,arguments);
519 }
520
521
522 template <class T> typename enable_if<And<is_class<T>, Not<is_container<T>>>,void>::T
523 populateFromObj(RESTProcess_t& r, T&obj)
524 {classdesc_access::access_RESTProcess<T>()(r,"",obj);}
525
526 template <class T> typename enable_if<Or<Not<is_class<T>>, is_container<T>>,void>::T
527 populateFromObj(RESTProcess_t& r, T&obj)
528 {}
529
530 template <class T> RESTProcess_t::RESTProcess_t(T&obj) {populateFromObj(*this,obj);}
531
532 template <class T, class...A> void RESTProcess_t::addFactory
533 (const string& typeName,const std::function<void(const std::string& objName)>& callback)
534 {
535 std::function<void(const std::string& name, A... args)> factory=
536 [this,callback](const std::string& name, A... args) {
537 auto rp=make_unique<RESTProcessHeapObject<T>>();
538 rp->obj=make_unique<T>(std::forward<A>(args)...);
539 add(name,rp.release());
540 callback(name);
541 };
542
543 add(typeName, new RESTProcessFunction<decltype(factory),void>(factory));
544 }
545
546 template <class T>
547 typename enable_if<
548 And<
551 >, RPPtr>::T makeRESTProcessRef(T& obj)
552 {return std::make_shared<RESTProcessObject<T>>(obj);}
553
554 template <class T>
555 typename enable_if<
556 And<
557 is_sequence<T>,
558 Not<is_base_of<MultiArrayBase,T>>
559 >, RPPtr>::T
560 makeRESTProcessRef(T& obj)
561 {return std::make_shared<RESTProcessSequence<T>>(obj);}
562
563 template <class T>
566 {return std::make_shared<RESTProcessMultiArray<T>>(obj);}
567
568 template <class T>
569 typename enable_if<is_smart_ptr<T>, RPPtr>::T
571 {return std::make_shared<RESTProcessPtr<T>>(obj);}
572}
573
574namespace classdesc_access
575{
576 namespace cd=classdesc;
577#if defined(__cplusplus) && __cplusplus>=201103L
578 template <class F>
579 struct access_RESTProcess<std::function<F>>
580 {
581 void operator()(cd::RESTProcess_t& r, const cd::string& d, const std::function<F>& a)
582 {r.add(d, new cd::RESTProcessFunction<std::function<F>>(a));}
583 };
584#endif
585
586#ifdef CLASSDESC_JSON_PACK_BASE_H
587 template <>
588 struct access_RESTProcess<cd::json_pack_t>: public cd::NullDescriptor<cd::RESTProcess_t> {};
589#endif
590
591}
592
593
594#endif
RPPtr keys() const override
returns a list of keys if this is an associative container, otherwise void
Definition RESTProcess_base.h:1019
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:309
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:141
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:87
void erase(const REST_PROCESS_BUFFER &index) override
erase an element - by position for sequences, by key for associative containers
Definition RESTProcess_base.h:1014
Signature functionSignature() const
return signature for a function type F
Definition RESTProcess_epilogue.h:169
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:94
Definition RESTProcess_base.h:1480
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:272
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:130
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:80
Definition json_pack_base.h:99
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
const T & keyOf(const T &x)
utility key extraction function for associative containers
Definition classdesc.h:526
std::string idx(const std::string &prefix, size_t i)
utility for generating index keys (for use with arrays)
Definition xml_common.h:14
enable_if< And< Not< is_const< T > >, is_pair< typenameT::value_type > >, void >::T assignElem(T &obj, const K &k, const REST_PROCESS_BUFFER &x)
assign x if T is a map
Definition RESTProcess_base.h:903
enable_if< And< Not< is_container< T > >, Not< is_smart_ptr< T > > >, RPPtr >::T makeRESTProcessRef(T &obj)
create an appropriate RESTProcess object referring to the argument.
Definition RESTProcess_epilogue.h:551
void RPAC_insert(T &obj, const REST_PROCESS_BUFFER &arguments)
insert element into an associative container
Definition RESTProcess_base.h:846
enable_if< Not< functional::is_nonmember_function_ptr< T > >, void >::T RESTProcess(RESTProcess_t &, const std::string &, T &)
descriptor for generating building REST processing registry
Definition RESTProcess_epilogue.h:177
STL namespace.
Definition classdesc.h:420
Definition RESTProcess_epilogue.h:159
Definition RESTProcess_epilogue.h:238
Definition classdesc.h:405
helper for constructing null descriptors
Definition classdesc.h:1106
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:293
handle setting and getting of objects
Definition RESTProcess_base.h:449
std::string type() const override
return type name of this
Definition RESTProcess_epilogue.h:154
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:124
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:59
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:187
RESTProcess_t list() const override
return list of subcommands to this
Definition RESTProcess_epilogue.h:127
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:382
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:66
RPPtr process(const string &remainder, const REST_PROCESS_BUFFER &arguments) override
Definition RESTProcess_epilogue.h:401
std::vector< Signature > signature() const override
return signature(s) of the operations
Definition RESTProcess_epilogue.h:73
REST processor registry.
Definition RESTProcess_base.h:351
void addFactory(const std::string &typeName, const std::function< void(const std::string &objName)> &callback=nullptr)
Definition RESTProcess_epilogue.h:533
void add(string d, RESTProcessBase *rp)
ownership of rp is passed
Definition RESTProcess_base.h:360
Definition signature.h:18
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
Definition function.h:50
determines if T is a container
Definition classdesc.h:358
Definition classdesc.h:571
Definition RESTProcess_base.h:1693