Skip to content

Latest commit

 

History

History
198 lines (159 loc) · 5.32 KB

209.md

File metadata and controls

198 lines (159 loc) · 5.32 KB
Info

Example

template<class TPolicy>
struct foo : TPolicy {
  static constexpr auto bar() {
    return TPolicy::bar();
  }
};

template<auto N>
struct policy { static constexpr auto bar() { return N; } };

static_assert(0 == foo<policy<0>>::bar());
static_assert(42 == foo<policy<42>>::bar());

https://godbolt.org/z/Mhhs9q

Puzzle

  • Can you implement foo::bar which is noexcept when noexcept_policy is set and returns a sum of execute_policy::bar calls?

    • Types not satisfying any policy should be ignored
    • Double points for explaining what advantages Policy Based Design has over passing Enums/Booleans?
template<class... TPolicies>
struct foo {
  static constexpr auto bar() noexcept/*TODO*/ {
    return 0;/*TODO*/
  }
};

template<auto N> struct execute_policy { static constexpr auto bar() { return N; } };
struct noexcept_policy { };
struct ignore { };

static_assert(not noexcept(foo<>::bar()));
static_assert(not noexcept(foo<ignore>::bar()));
static_assert(noexcept(foo<noexcept_policy>::bar()));
static_assert(noexcept(foo<noexcept_policy, ignore>::bar()));
static_assert(noexcept(foo<ignore, noexcept_policy, ignore>::bar()));
static_assert(noexcept(foo<ignore, noexcept_policy, ignore, execute_policy<0>>::bar()));

static_assert(42 == foo<execute_policy<42>>::bar());
static_assert(42 == foo<ignore, execute_policy<42>>::bar());
static_assert(42 == foo<ignore, execute_policy<42>, ignore>::bar());
static_assert(100 == foo<ignore, execute_policy<42>, ignore, execute_policy<58>>::bar());
static_assert(3 == foo<execute_policy<1>, noexcept_policy, execute_policy<2>, noexcept_policy>::bar());

https://godbolt.org/z/a6M6sr

Solutions

template<class... TPolicies>
struct foo {
  template<class T > struct  no_bar{ constexpr static bool value = !requires{ T::bar();}; };
  static constexpr auto bar() noexcept( !std::is_same_v< mp_find<mp_list<TPolicies...>,  class noexcept_policy >, mp_size<mp_list<TPolicies...> > > )/*TODO*/ {
    using L = mp_remove_if<mp_list< TPolicies... >, no_bar >;
    return []< class ... Ts >( mp_list<Ts... > ){ return ( (Ts::bar()) + ... + 0 ) ;}( L{} );
  }
};

https://godbolt.org/z/azhGoh

// Advantages of policies? They're basically the https://en.wikipedia.org/wiki/Strategy_pattern
// Decoupled interfaces, adherence to the open/closed principle, etc.

template<class... TPolicies>
struct foo {
  static constexpr auto bar() noexcept((std::is_same_v<TPolicies, struct noexcept_policy> or ...)) {
    constexpr auto run_bar = []<class TPolicy>() {
      if constexpr (requires { TPolicy::bar(); }) {
        return TPolicy::bar();
      } else {
        return 0;
      }
    };
    return (0 + ... + run_bar.template operator()<TPolicies>());
  }
};

https://godbolt.org/z/cvzr7q

struct noexcept_policy { };

template<class...>
struct has_noexcept_policy;

template<>
struct has_noexcept_policy<> {
  static constexpr auto value = false;
};

template<class T, class... Ts>
struct has_noexcept_policy<T, Ts...> {
  static constexpr auto value = [] {
    if constexpr (std::is_same_v<T, noexcept_policy>) {
      return true;
    } else {
      return has_noexcept_policy<Ts...>::value;
    }
  }();
};

template<class TPolicy>
struct execute_policy_bar {
  static constexpr auto value = [] {
    if constexpr (requires { { TPolicy::bar() } -> std::integral; }) {
      return TPolicy::bar();
    } else {
      return 0;
    }
  }();
};

template<class... TPolicies>
struct foo {
  static constexpr auto bar() noexcept(has_noexcept_policy<TPolicies...>::value) {
    return (0 + ... + execute_policy_bar<TPolicies>::value);
  }
};

https://godbolt.org/z/Pn1x3n

namespace detail {
template<class T>
concept has_func_bar = requires { T::bar(); };
}

template<class... TPolicies>
struct foo {
  static constexpr auto has_noexcept_policy = (std::is_same_v<TPolicies, struct noexcept_policy> or ...);

  [[nodiscard]] static constexpr auto bar() noexcept(has_noexcept_policy) {
    [[maybe_unused]] constexpr auto run_execute_policy = []<class TPolicy>(){
       if constexpr(detail::has_func_bar<TPolicy>) {
           return TPolicy{}.bar();
       } else {
           return 0;
       }
    };

    return (run_execute_policy.template operator()<TPolicies>() + ... + 0);
  }
};

https://godbolt.org/z/KWTqYe

template<typename T> concept HasBar = requires(T) {  T::bar(); };
template<HasBar T> auto constexpr CallBar() { return T::bar(); }
template<typename T> auto constexpr CallBar() { return 0; }

template<class... TPolicies>
struct foo {
  static constexpr auto bar() noexcept((std::is_same_v<TPolicies, noexcept_policy> || ...)) {
      return (CallBar<TPolicies>() + ...+ 0);
  }
};

https://godbolt.org/z/fa199r

template<class... TPolicies>
struct foo {
  static constexpr auto bar() noexcept((std::is_same_v<struct noexcept_policy, TPolicies> or ...)) {
    return ([] {
      if constexpr (requires { TPolicies::bar(); }) {
        return TPolicies::bar();
      } else {
        return 0;
      }
    }() + ... + 0);
  }
};

https://godbolt.org/z/65r6bv