message.h 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. //
  2. // message.h
  3. // cli
  4. //
  5. // Created by Sam Jaffe on 10/10/20.
  6. // Copyright © 2020 Sam Jaffe. All rights reserved.
  7. //
  8. #pragma once
  9. #include <iostream>
  10. #include <memory>
  11. #include <tuple>
  12. namespace cli { namespace detail {
  13. template <typename T, size_t ...Is>
  14. void print(std::ostream &os, T const & tup, std::index_sequence<Is...>) {
  15. os << std::boolalpha;
  16. using swallow = int[];
  17. (void)swallow{0, ((void)(os << std::get<Is>(tup)), 0)...};
  18. os << std::noboolalpha;
  19. }
  20. template <typename T> struct up_string { using type = std::remove_reference_t<T>; };
  21. template <size_t N> struct up_string<char const(&)[N]> {
  22. using type = std::string;
  23. };
  24. template <typename T> using up_string_t = typename up_string<T>::type;
  25. }}
  26. namespace cli {
  27. struct message {
  28. virtual ~message() = default;
  29. virtual void print(std::ostream &) const = 0;
  30. };
  31. template <typename ...T>
  32. struct message_impl : public message {
  33. std::tuple<T...> tuple;
  34. message_impl(std::tuple<T...> &&tuple) : tuple(std::move(tuple)) {}
  35. void print(std::ostream &os) const override {
  36. detail::print(os, tuple, std::make_index_sequence<sizeof...(T)>{});
  37. }
  38. };
  39. template <typename ...Args>
  40. auto make_message(Args &&...args) {
  41. using detail::up_string_t;
  42. using message_t = message_impl<up_string_t<Args>...>;
  43. auto tuple = std::make_tuple(std::forward<up_string_t<Args>>(args)...);
  44. return std::make_shared<message_t>(std::move(tuple));
  45. }
  46. }