Skip to content

Latest commit

 

History

History
179 lines (140 loc) · 4.11 KB

231.md

File metadata and controls

179 lines (140 loc) · 4.11 KB
Info

Example

template<class... TEvents>
struct ihandler : ihandler<TEvents>... {
  virtual ~ihandler() noexcept = default;
  using ihandler<TEvents>::on...;
};

template<class TEvent> struct ihandler<TEvent> {
  virtual ~ihandler() noexcept = default;
  virtual auto on(const TEvent&) -> bool = 0;
};

int main() {
  struct foo {};
  struct bar {};

  struct handler : ihandler<foo, bar> {
    auto on(const foo&) -> bool override { return true; }
    auto on(const bar&) -> bool override { return false; }
  };

  std::unique_ptr<ihandler<foo, bar>> h = std::make_unique<handler>();
  assert(h->on(foo{}));
  assert(not h->on(bar{}));
}

https://godbolt.org/z/ffr1TaGhq

Puzzle

  • Can you implement handler which will implement an interface T for given Ts... and returns Ts::value?
template<class... TEvents>
struct ihandler : ihandler<TEvents>... {
  virtual ~ihandler() noexcept = default;
  using ihandler<TEvents>::on...;
};

template<class TEvent> struct ihandler<TEvent> {
  virtual ~ihandler() noexcept = default;
  virtual auto on(const TEvent&) -> bool = 0;
};

template<template<class...> class T, class... Ts>
struct handler final; // TODO

int main() {
  using namespace boost::ut;

  "handler"_test = [] {
    struct foo { bool value{}; };
    struct bar { bool value{}; };

    auto h = std::make_unique<handler<ihandler, foo, bar>>();

    expect(h->on(foo{.value = true}) and
           static_cast<ihandler<foo>*>(h.get())->on(foo{.value = true})
    );

    expect(not h->on(bar{.value = false}) and
           not static_cast<ihandler<bar>*>(h.get())->on(bar{.value = false})
    );
  };
}

https://godbolt.org/z/hez4KvcnM

Solutions

template<class T, template<class...> class  U>
struct handler_helper:U<T>
{
    auto on(const T& t) -> bool override{
        return t.value;
    }
};

template<template<class...> class T, class... Ts>
struct handler final : handler_helper<Ts,T> ...
{
    using handler_helper<Ts,T>::on...;
};

https://godbolt.org/z/bhqMdMj5E

namespace detail {
template<template<class...> class I, class T>
struct handler : I<T> {
  auto on(const T& t) -> bool override {
    return t.value;
  }
};
} // namespace detail

template<template<class...> class T, class... Ts>
struct handler final : detail::handler<T, Ts>... {
  using detail::handler<T, Ts>::on...;
};

https://godbolt.org/z/vfvee6bP1

namespace detail {
template <template<class> class Interface, class TEvent>
struct handler_impl : Interface<TEvent> {
  auto on(const TEvent& event) -> bool override { return event.value; }
};
}

template <template<class> class Interface, class... TEvents>
struct handler final : detail::handler_impl<Interface, TEvents>... {
  using detail::handler_impl<Interface, TEvents>::on...;
};

https://godbolt.org/z/7xEsM16jM

template<template<class...> class T, class... Ts>
struct handler final : handler<T, Ts>... {
    using handler<T, Ts>::on...;
};

template<template<class...> class T, class TEvent>
struct handler<T, TEvent> : T<TEvent> {
    auto on(const TEvent& event) -> bool final {
        return event.value;
    }
};

https://godbolt.org/z/Pe491e6E1

namespace detail {
template <template <class...> class TContainer, class T>
struct handler_impl : TContainer<T> {
  [[nodiscard]] constexpr auto on(const T& t) -> bool override {
    return t.value;
  }
};
}  // namespace detail

template <template <class...> class T, class... Ts>
struct handler final : detail::handler_impl<T, Ts>... {
  using detail::handler_impl<T, Ts>::on...;
};

https://godbolt.org/z/W1xavY13r

template<class T>
struct on_method : ihandler<T> {
    bool on(T const& t) { return t.value; }
};

template<template<class...> class T, class... Ts>
struct handler final : on_method<Ts>... {
    using on_method<Ts>::on...;
};

https://godbolt.org/z/8vG89YY11