fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <memory>
  5. #include <typeinfo>
  6. #include <typeindex>
  7. #include <type_traits>
  8. #include <utility>
  9. #include <tuple>
  10.  
  11. using namespace std;
  12.  
  13.  
  14. struct UnknownTypeForOneOf;
  15.  
  16. template <typename Want_, typename... Types_>
  17. struct SelectOneOfType;
  18.  
  19. template <typename Want_>
  20. struct SelectOneOfType<Want_>
  21. {
  22. typedef UnknownTypeForOneOf Type;
  23. };
  24.  
  25. template <typename Want_, typename Try_, typename... Rest_>
  26. struct SelectOneOfType<Want_, Try_, Rest_...>
  27. {
  28. typedef typename std::conditional<
  29. std::is_same<Want_, Try_>::value,
  30. Try_,
  31. typename SelectOneOfType<Want_, Rest_...>::Type
  32. >::type Type;
  33. };
  34.  
  35. template <typename Type_>
  36. struct ParameterTypes;
  37.  
  38. template <typename C_, typename R_, typename P_>
  39. struct ParameterTypes<R_ (C_::*)(P_)>
  40. {
  41. typedef P_ FirstParameterType;
  42. typedef R_ ReturnType;
  43. };
  44.  
  45. template <typename C_, typename R_, typename P_>
  46. struct ParameterTypes<R_ (C_::*)(P_) const>
  47. {
  48. typedef P_ FirstParameterType;
  49. typedef R_ ReturnType;
  50. };
  51.  
  52. template <typename Lambda_>
  53. struct LambdaParameterTypes
  54. {
  55. typedef typename ParameterTypes<decltype(&Lambda_::operator())>::FirstParameterType FirstParameterType;
  56. typedef typename ParameterTypes<decltype(&Lambda_::operator())>::ReturnType ReturnType;
  57. };
  58.  
  59. template <typename Type_>
  60. struct OneOfVisitorVisit
  61. {
  62. virtual void visit(Type_ &) = 0;
  63. };
  64.  
  65. template <typename... Types_>
  66. struct OneOfVisitor :
  67. OneOfVisitorVisit<Types_>...
  68. {
  69. };
  70.  
  71. template <typename Visitor_, typename Underlying_, typename Result_, typename... Types_>
  72. struct OneOfVisitorWrapperVisit;
  73.  
  74. template <typename Visitor_, typename Underlying_, typename Result_>
  75. struct OneOfVisitorWrapperVisit<Visitor_, Underlying_, Result_> :
  76. Visitor_
  77. {
  78. Underlying_ & underlying;
  79. std::function<Result_ ()> execute;
  80.  
  81. OneOfVisitorWrapperVisit(Underlying_ & u) :
  82. underlying(u)
  83. {
  84. }
  85. };
  86.  
  87. template <typename Visitor_, typename Underlying_, typename Result_, typename Type_, typename... Rest_>
  88. struct OneOfVisitorWrapperVisit<Visitor_, Underlying_, Result_, Type_, Rest_...> :
  89. OneOfVisitorWrapperVisit<Visitor_, Underlying_, Result_, Rest_...>
  90. {
  91. OneOfVisitorWrapperVisit(Underlying_ & u) :
  92. OneOfVisitorWrapperVisit<Visitor_, Underlying_, Result_, Rest_...>(u)
  93. {
  94. }
  95.  
  96. Result_ visit_returning(Type_ & t)
  97. {
  98. return this->underlying.visit(t);
  99. }
  100.  
  101. virtual void visit(Type_ & t)
  102. {
  103. this->execute = std::bind(&OneOfVisitorWrapperVisit::visit_returning, this, std::ref(t));
  104. }
  105. };
  106.  
  107. template <typename Underlying_, typename Result_, typename... Types_>
  108. struct OneOfVisitorWrapper :
  109. OneOfVisitorWrapperVisit<OneOfVisitor<Types_...>, Underlying_, Result_, Types_...>
  110. {
  111. OneOfVisitorWrapper(Underlying_ & u) :
  112. OneOfVisitorWrapperVisit<OneOfVisitor<Types_...>, Underlying_, Result_, Types_...>(u)
  113. {
  114. }
  115. };
  116.  
  117. template <typename... Types_>
  118. struct OneOfValueBase
  119. {
  120. virtual ~OneOfValueBase() = 0;
  121.  
  122. virtual void accept(OneOfVisitor<Types_...> &) = 0;
  123. virtual void accept(OneOfVisitor<const Types_...> &) const = 0;
  124. };
  125.  
  126. template <typename... Types_>
  127. OneOfValueBase<Types_...>::~OneOfValueBase() = default;
  128.  
  129. template <typename Type_, typename... Types_>
  130. struct OneOfValue :
  131. OneOfValueBase<Types_...>
  132. {
  133. Type_ value;
  134.  
  135. OneOfValue(const Type_ & type) :
  136. value(type)
  137. {
  138. }
  139.  
  140. virtual void accept(OneOfVisitor<Types_...> & visitor)
  141. {
  142. static_cast<OneOfVisitorVisit<Type_> &>(visitor).visit(value);
  143. }
  144.  
  145. virtual void accept(OneOfVisitor<const Types_...> & visitor) const
  146. {
  147. static_cast<OneOfVisitorVisit<const Type_> &>(visitor).visit(value);
  148. }
  149. };
  150.  
  151. template <typename... Types_>
  152. class OneOf
  153. {
  154. private:
  155. std::unique_ptr<OneOfValueBase<Types_...> > _value;
  156.  
  157. public:
  158. template <typename Type_>
  159. OneOf(const Type_ & value) :
  160. _value(new OneOfValue<typename SelectOneOfType<Type_, Types_...>::Type, Types_...>{value})
  161. {
  162. }
  163.  
  164. OneOf(const OneOf & other) = delete;
  165.  
  166. OneOf(OneOf && other) :
  167. _value(std::move(other._value))
  168. {
  169. }
  170.  
  171. template <typename Type_>
  172. OneOf & operator= (const Type_ & value)
  173. {
  174. _value.reset(new OneOfValue<typename SelectOneOfType<Type_, Types_...>::Type, Types_...>{value});
  175. return *this;
  176. }
  177.  
  178. OneOf & operator= (const OneOf & other) = delete;
  179.  
  180. OneOf & operator= (OneOf && other)
  181. {
  182. _value = std::move(other._value);
  183. return *this;
  184. }
  185.  
  186. OneOfValueBase<Types_...> & value()
  187. {
  188. return *_value;
  189. }
  190.  
  191. const OneOfValueBase<Types_...> & value() const
  192. {
  193. return *_value;
  194. }
  195. };
  196.  
  197. template <typename Visitor_, typename Result_, typename OneOf_>
  198. struct OneOfVisitorWrapperTypeFinder;
  199.  
  200. template <typename Visitor_, typename Result_, typename... Types_>
  201. struct OneOfVisitorWrapperTypeFinder<Visitor_, Result_, const OneOf<Types_...> &>
  202. {
  203. typedef OneOfVisitorWrapper<Visitor_, Result_, const Types_...> Type;
  204. };
  205.  
  206. template <typename Visitor_, typename Result_, typename... Types_>
  207. struct OneOfVisitorWrapperTypeFinder<Visitor_, Result_, OneOf<Types_...> &>
  208. {
  209. typedef OneOfVisitorWrapper<Visitor_, Result_, Types_...> Type;
  210. };
  211.  
  212. template <typename Result_, typename OneOf_, typename Visitor_>
  213. Result_
  214. accept_returning(OneOf_ && one_of, Visitor_ && visitor)
  215. {
  216. typename OneOfVisitorWrapperTypeFinder<Visitor_, Result_, OneOf_>::Type visitor_wrapper(visitor);
  217. one_of.value().accept(visitor_wrapper);
  218. return visitor_wrapper.execute();
  219. }
  220.  
  221. template <typename OneOf_, typename Visitor_>
  222. void accept(OneOf_ && one_of, Visitor_ && visitor)
  223. {
  224. accept_returning<void>(one_of, visitor);
  225. }
  226.  
  227. template <typename Result_, typename... Funcs_>
  228. struct LambdaVisitor;
  229.  
  230. template <typename Result_>
  231. struct LambdaVisitor<Result_>
  232. {
  233. void visit(struct NotReallyAType);
  234. };
  235.  
  236. template <typename Result_, typename Func_, typename... Rest_>
  237. struct LambdaVisitor<Result_, Func_, Rest_...> :
  238. LambdaVisitor<Result_, Rest_...>
  239. {
  240. Func_ & func;
  241.  
  242. LambdaVisitor(Func_ & f, Rest_ & ... rest) :
  243. LambdaVisitor<Result_, Rest_...>(rest...),
  244. func(f)
  245. {
  246. }
  247.  
  248. Result_ visit(typename LambdaParameterTypes<Func_>::FirstParameterType & v)
  249. {
  250. return func(v);
  251. }
  252.  
  253. using LambdaVisitor<Result_, Rest_...>::visit;
  254. };
  255.  
  256. template <typename... Funcs_>
  257. struct AllReturnSame;
  258.  
  259. template <typename Func_>
  260. struct AllReturnSame<Func_>
  261. {
  262. enum { value = true };
  263. };
  264.  
  265. template <typename A_, typename B_, typename... Funcs_>
  266. struct AllReturnSame<A_, B_, Funcs_...>
  267. {
  268. enum { value = std::is_same<typename LambdaParameterTypes<A_>::ReturnType, typename LambdaParameterTypes<B_>::ReturnType>::value &&
  269. AllReturnSame<B_, Funcs_...>::value };
  270. };
  271.  
  272. template <typename...>
  273. struct SeenSoFar
  274. {
  275. };
  276.  
  277. template <typename...>
  278. struct ExtendSeenSoFar;
  279.  
  280. template <typename New_, typename... Current_>
  281. struct ExtendSeenSoFar<New_, SeenSoFar<Current_...> >
  282. {
  283. typedef SeenSoFar<Current_..., New_> Type;
  284. };
  285.  
  286. template <typename...>
  287. struct AlreadySeen;
  288.  
  289. template <typename Query_>
  290. struct AlreadySeen<SeenSoFar<>, Query_>
  291. {
  292. enum { value = false };
  293. };
  294.  
  295. template <typename Query_, typename A_, typename... Rest_>
  296. struct AlreadySeen<SeenSoFar<A_, Rest_...>, Query_>
  297. {
  298. enum { value = std::is_same<Query_, A_>::value || AlreadySeen<SeenSoFar<Rest_...>, Query_>::value };
  299. };
  300.  
  301. template <typename...>
  302. struct OneOfDeduplicatorBuilder;
  303.  
  304. template <typename... Values_>
  305. struct OneOfDeduplicatorBuilder<SeenSoFar<Values_...> >
  306. {
  307. typedef OneOf<Values_...> Type;
  308. };
  309.  
  310. template <typename SeenSoFar_, typename Next_, typename... Funcs_>
  311. struct OneOfDeduplicatorBuilder<SeenSoFar_, Next_, Funcs_...>
  312. {
  313. typedef typename std::conditional<
  314. AlreadySeen<SeenSoFar_, Next_>::value,
  315. typename OneOfDeduplicatorBuilder<SeenSoFar_, Funcs_...>::Type,
  316. typename OneOfDeduplicatorBuilder<typename ExtendSeenSoFar<Next_, SeenSoFar_>::Type, Funcs_...>::Type
  317. >::type Type;
  318. };
  319.  
  320. template <typename... Funcs_>
  321. struct OneOfDeduplicator
  322. {
  323. typedef typename OneOfDeduplicatorBuilder<SeenSoFar<>, Funcs_...>::Type Type;
  324. };
  325.  
  326. template <typename... Funcs_>
  327. struct WhenReturnType;
  328.  
  329. template <typename FirstFunc_, typename... Funcs_>
  330. struct WhenReturnType<FirstFunc_, Funcs_...>
  331. {
  332. typedef typename std::conditional<
  333. AllReturnSame<FirstFunc_, Funcs_...>::value,
  334. typename LambdaParameterTypes<FirstFunc_>::ReturnType,
  335. typename OneOfDeduplicator<
  336. typename LambdaParameterTypes<FirstFunc_>::ReturnType,
  337. typename LambdaParameterTypes<Funcs_>::ReturnType ...>::Type
  338. >::type Type;
  339. };
  340.  
  341. template <typename Val_, typename... Funcs_>
  342. typename WhenReturnType<Funcs_...>::Type
  343. when(Val_ && val, Funcs_ && ... funcs)
  344. {
  345. LambdaVisitor<typename WhenReturnType<Funcs_...>::Type, Funcs_...> visitor(funcs...);
  346. return accept_returning<typename WhenReturnType<Funcs_...>::Type>(val, visitor);
  347. }
  348.  
  349. struct Base {
  350. Base(const string &i = "Base"):i(i){}
  351. virtual ~Base(){}
  352.  
  353. string i;
  354. };
  355.  
  356. struct A : public Base {
  357. A():Base("A"){}
  358. };
  359.  
  360. struct B : public Base {
  361. B():Base("B"){}
  362. };
  363.  
  364. struct C : public Base {
  365. C():Base("C"){}
  366. };
  367.  
  368. struct Node {
  369.  
  370. template<typename ContainerObjectType>
  371. void castAndAdd(const shared_ptr<Base> &base, vector<ContainerObjectType> &container){
  372. //base case do nothing
  373. }
  374.  
  375. template<typename ContainerObjectType, typename T>
  376. void castAndAdd(const shared_ptr<Base> &base, vector<ContainerObjectType> &container){
  377. if(typeid(*base) == typeid(T)){
  378. cout << "Adding: " << base->i << endl;
  379. container.push_back(std::static_pointer_cast<T>(base));
  380. }
  381. }
  382.  
  383. template<typename ContainerObjectType, typename T, typename T2, typename ...V>
  384. void castAndAdd(const shared_ptr<Base> &base, vector<ContainerObjectType> &container){
  385. if(typeid(*base) == typeid(T)){
  386. cout << "Adding: " << base->i << endl;
  387. container.push_back(std::static_pointer_cast<T>(base));
  388. }else{
  389. castAndAdd<ContainerObjectType, T2, V...>(base, container);
  390. }
  391. }
  392.  
  393. template<typename ...T>
  394. vector<OneOf<shared_ptr<T>...>> components(){
  395. vector<OneOf<shared_ptr<T>...>> results;
  396. for(auto&& item : contents){
  397. castAndAdd<OneOf<shared_ptr<T>...>, T...>(item, results);
  398. }
  399. return results;
  400. }
  401.  
  402. vector<shared_ptr<Base>> contents;
  403. };
  404.  
  405.  
  406. int main() {
  407. Node root;
  408. root.contents.push_back(make_shared<Base>());
  409. root.contents.push_back(make_shared<C>());
  410. root.contents.push_back(make_shared<B>());
  411. root.contents.push_back(make_shared<A>());
  412. root.contents.push_back(make_shared<C>());
  413.  
  414. auto components = root.components<A, B>();
  415.  
  416. for(auto&& component : components){
  417. when(component,
  418. [](const std::shared_ptr<B> &item){
  419. cout << "B found: " << item->i << std::endl;
  420. },
  421. [](const std::shared_ptr<C> &item){
  422. cout << "C found: " << item->i << std::endl;
  423. },
  424. [](const std::shared_ptr<A> &item){
  425. cout << "A found: " << item->i << std::endl;
  426. });
  427. }
  428.  
  429. return 0;
  430. }
Success #stdin #stdout 0s 3288KB
stdin
Standard input is empty
stdout
Adding: B
Adding: A
B found: B
A found: A