Advertisement
Guest User

Translator pattern in C++

a guest
Apr 1st, 2019
496
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.64 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <utility>
  4.  
  5. template <class Base1, class Base2>
  6. struct OverloadSet
  7.   : public Base1
  8.   , public Base2
  9. {
  10.     OverloadSet(Base1 const& b1, Base2 const& b2) : Base1(b1), Base2(b2) {}
  11.     OverloadSet(Base1&& b1, Base2&& b2)
  12.       : Base1(std::move(b1)), Base2(std::move(b2))
  13.     {
  14.     }
  15.     using Base1::operator();
  16.     using Base2::operator();
  17. };
  18.  
  19. template <class F1, class F2>
  20. auto overload_set(F1&& func1, F2&& func2)
  21.     -> OverloadSet<typename std::decay<F1>::type, typename std::decay<F2>::type>
  22. {
  23.     return {std::forward<F1>(func1), std::forward<F2>(func2)};
  24. }
  25. class read_name_t
  26. {
  27. };
  28. #define READ_FIELD(name, field)                                               \
  29.     overload_set(                                                             \
  30.         [](auto&& object) -> decltype(object.field) { return object.field; }, \
  31.         [](read_name_t) -> decltype(auto) { return name; })
  32.  
  33. template <class Reader>
  34. class OptionalReader
  35. {
  36.    public:
  37.     Reader read;
  38.     template <class Consumer, class Object>
  39.     void maybeConsume(Consumer&& consume, Object&& obj) const
  40.     {
  41.         maybeConsume(consume, obj, 0);
  42.     }
  43.  
  44.    private:
  45.     template <class...>
  46.     using ignore_t = void;
  47.  
  48.     template <class Consumer, class Object>
  49.     auto maybeConsume(Consumer& consume, Object& obj, int) const
  50.         -> ignore_t<decltype(consume(read(read_name_t()), read(obj)))>
  51.     {
  52.         consume(read(read_name_t()), read(obj));
  53.     }
  54.  
  55.     template <class Consumer, class Object>
  56.     auto maybeConsume(Consumer&, Object&, long) const -> void
  57.     {
  58.     }
  59. };
  60. template <class... OptionalApplier>
  61. class Translator : public OptionalApplier...
  62. {
  63.    public:
  64.     Translator(OptionalApplier const&... appliers)
  65.       : OptionalApplier(appliers)...
  66.     {
  67.     }
  68.     Translator(OptionalApplier&&... appliers) : OptionalApplier(appliers)... {}
  69.  
  70.     template <class Consumer, class Object>
  71.     void translate(Consumer&& consume, Object&& o) const
  72.     {
  73.         char _[] = {((void)OptionalApplier::maybeConsume(consume, o), '\0')...};
  74.         (void)_;
  75.     }
  76. };
  77. template <class... Reader>
  78. auto makeTranslator(Reader const&... readers)
  79.     -> Translator<OptionalReader<Reader>...>
  80. {
  81.     return {OptionalReader<Reader>{readers}...};
  82. }
  83.  
  84. int main()
  85. {
  86.     struct Car1
  87.     {
  88.         std::string getMake() { return "Toyota"; }
  89.         std::string getModel() { return "Prius"; }
  90.     };
  91.     struct Car2
  92.     {
  93.         std::string getMake() { return "Toyota"; }
  94.         int         getYear() { return 2017; };
  95.     };
  96.     struct Car3
  97.     {
  98.         std::string getModel() { return "Prius"; }
  99.         int         getYear() { return 2017; }
  100.     };
  101.     struct Car4
  102.     {
  103.         long long getSerial() { return 2039809809820390; }
  104.     };
  105.  
  106.     auto translator = makeTranslator(READ_FIELD("getMake()", getMake()),
  107.                                      READ_FIELD("getYear()", getYear()),
  108.                                      READ_FIELD("getModel()", getModel()),
  109.                                      READ_FIELD("getSerial()", getSerial()));
  110.  
  111.     auto processField = [](std::string const& field, auto const& value) {
  112.         std::cout << "    \"" << field << "\": " << value << "\n";
  113.     };
  114.  
  115.     Car1 car1;
  116.     std::cout << "Reading car 1: \n";
  117.     translator.translate(processField, car1);
  118.  
  119.     Car2 car2;
  120.     std::cout << "Reading car 2: \n";
  121.     translator.translate(processField, car2);
  122.  
  123.     Car3 car3;
  124.     std::cout << "Reading car 3: \n";
  125.     translator.translate(processField, car3);
  126.  
  127.     Car4 car4;
  128.     std::cout << "Reading car 4: \n";
  129.     translator.translate(processField, car4);
  130. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement