Skip to content

Latest commit

 

History

History
144 lines (109 loc) · 3.63 KB

299.md

File metadata and controls

144 lines (109 loc) · 3.63 KB
Info

Example

#include <concepts>

void foo(int i);
void bar(std::same_as<int> auto i);


int main() {
  foo(42.0); // implicit conversion
  bar(42.0); // error: contraint not satisifed
}

https://godbolt.org/z/v45nYdaT7

Puzzle

  • Can you implement conversion safe invoke[args...]?

    • Note: Doesn't allow implicit conversions neither for parameters nor for the return type
struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](...); // TODO
} invoke;

auto foo(int, double, float) -> void;

constexpr auto can_invoke_with = []<class R, class... Ts>(R fn(Ts...), auto&&... args) {
  return requires { { invoke.template operator[]<R, Ts...>(fn, std::forward<decltype(args)>(args)...) } -> std::same_as<R>; };
};

static_assert(    can_invoke_with(foo, int{}, double{}, float{}));
static_assert(not can_invoke_with(foo, int{}, float{}, float{}));
static_assert(not can_invoke_with(foo, float{}, float{}, float{}));
static_assert(not can_invoke_with(foo, short{}, int{}, double{}, float{}));
static_assert(not can_invoke_with(foo, int{}, double{}, float{}, float{}));

https://godbolt.org/z/vz9sxssE4

Solutions

    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](R fn(Ts...), std::same_as<Ts> auto... ts ) -> R;

https://godbolt.org/z/T4rvx87Wo

  template<class R, class... Ts, class ...Ts2, ::std::enable_if_t<
    sizeof...(Ts) == sizeof...(Ts2) &&
    (::std::is_same_v<Ts, Ts2> && ...), int> = 0>
  [[nodiscard]] constexpr auto operator[](R fn(Ts...), Ts2... ts ) -> R;

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

struct {
  template <class R, class... Ts>
  [[nodiscard]] constexpr auto operator[](R fn(Ts...),
                                          std::same_as<Ts> auto&&... args)
      -> std::same_as<R> decltype(auto) {
    return fn(std::forward<Ts>(args)...);
  }
} invoke;

https://godbolt.org/z/cbGrTW74q

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](R fn(Ts...), std::same_as<Ts> auto&&... args){
        return fn(std::forward<decltype(args)>(args)...);
    }
} invoke;

https://godbolt.org/z/53jaMTK6z

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](auto&& fn, std::same_as<Ts> auto&&... args) -> std::same_as<R> auto {
        return fn(std::forward<Ts>(args)...);
    }
} invoke;

https://godbolt.org/z/Gjv51ev13

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](auto fn, std::same_as<Ts>auto ...params) -> std::same_as<R> auto {
        return fn(params...);
    };
} invoke;

https://godbolt.org/z/9vMh8sje6

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](auto F, auto... args) -> std::same_as<R> auto requires (std::same_as<Ts,decltype(args)> && ...) {
        return F(args...);
    };
} invoke;

https://godbolt.org/z/TjbzWd7dT

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](R fn(Ts...), std::same_as<Ts> auto&& ... args)->R;
} invoke;

https://godbolt.org/z/bz38Yb3c6

struct {
    template<class R, class... Ts>
    [[nodiscard]] constexpr auto operator[](auto f, std::same_as<Ts> auto &&...args){
        f(args...);
    }
} invoke;

https://godbolt.org/z/MP9nK16xr