out.h 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #pragma once
  2. #include <type_traits>
  3. #include <utility>
  4. #include <variant>
  5. namespace jvalidate::detail {
  6. constexpr struct discard_out_t {
  7. } discard_out;
  8. template <typename T>
  9. requires(std::is_same_v<T, std::decay_t<T>>)
  10. class out {
  11. private:
  12. T * ref_ = nullptr;
  13. public:
  14. out() = default;
  15. out(discard_out_t) {}
  16. out(T & ref) : ref_(&ref) {}
  17. explicit operator bool() const { return ref_; }
  18. template <typename U>
  19. requires std::is_constructible_v<T, U>
  20. void operator=(U && val) {
  21. if (ref_) {
  22. *ref_ = std::forward<U>(val);
  23. }
  24. return *this;
  25. }
  26. };
  27. template <typename T>
  28. requires(std::is_same_v<T, std::decay_t<T>>)
  29. class inout {
  30. private:
  31. std::variant<T, T *> ref_;
  32. public:
  33. inout(T && value) : ref_(std::move(value)) {}
  34. inout(T & ref) : ref_(&ref) {}
  35. operator T const &() const {
  36. struct {
  37. T const & operator()(T const & in) const { return in; }
  38. T const & operator()(T * in) const { return *in; }
  39. } visitor;
  40. return std::visit(visitor, ref_);
  41. }
  42. template <typename U>
  43. requires std::is_constructible_v<T, U>
  44. T const & operator=(U && val) {
  45. struct {
  46. U && val;
  47. T const & operator()(T & in) const { return in = std::forward<U>(val); }
  48. T const & operator()(T * in) const { return *in = std::forward<U>(val); }
  49. } visitor{std::forward<U>(val)};
  50. return std::visit(visitor, ref_);
  51. }
  52. };
  53. }