Информация об изменениях

Сообщение Re[6]: Множественный форвардинг в std::bind от 21.03.2024 16:17

Изменено 21.03.2024 16:31 rg45

Re[6]: Множественный форвардинг в std::bind
Здравствуйте, serg_joker, Вы писали:

_>Есть, где посмотреть в образовательных целях?


http://coliru.stacked-crooked.com/a/773ea192115f80cf

Всегда пожалуйста!

#include <concepts>
#include <functional>
#include <iostream>
#include <sstream>
#include <utility>

namespace util
{

template <typename...T>
struct Inherited : std::decay_t<T>... {};

template <typename> struct IsFreeFunction : std::false_type {};
template<typename R, typename...A> struct IsFreeFunction<R(A...)> : std::true_type {};
template <typename T> struct IsFreeFunction<T*> : IsFreeFunction<T> {};

template <typename T>
concept FreeFunction = IsFreeFunction<std::decay_t<T>>::value;

template <typename T>
concept FunctionObject =
std::is_class_v<std::decay_t<T>> &&
!requires { &Inherited < T, decltype([] {}) > ::operator(); };

template <typename T>
concept Function = FreeFunction<T> || FunctionObject<T>;

template <typename T>
concept Entity = !Function<T> && !std::same_as<T, void>;

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
using std::placeholders::_5;
using std::placeholders::_6;
using std::placeholders::_7;
using std::placeholders::_8;
using std::placeholders::_9;
using std::placeholders::_10;
using std::placeholders::_11;
using std::placeholders::_12;

template <typename> struct PlaceholderIndexTag;
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_1)>> : std::integral_constant<size_t, 0> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_2)>> : std::integral_constant<size_t, 1> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_3)>> : std::integral_constant<size_t, 2> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_4)>> : std::integral_constant<size_t, 3> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_5)>> : std::integral_constant<size_t, 4> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_6)>> : std::integral_constant<size_t, 5> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_7)>> : std::integral_constant<size_t, 6> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_8)>> : std::integral_constant<size_t, 7> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_9)>> : std::integral_constant<size_t, 8> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_10)>> : std::integral_constant<size_t, 9> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_11)>> : std::integral_constant<size_t, 10> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_12)>> : std::integral_constant<size_t, 11> {};

template <typename T>
concept Placeholder = (Entity<T> || Function<T>) && requires {
   PlaceholderIndexTag<std::decay_t<T>>::value;
};

template <Placeholder T>
inline constexpr size_t PlaceholderIndex = PlaceholderIndexTag<std::decay_t<T>>::value;

template <Function F, typename...X>
class Bind
{
public:
   constexpr Bind() = default;

   template <Function FF, typename...XX>
   constexpr Bind(FF&& f, XX&&...x) : m_f(std::forward<FF>(f)), m_x(std::forward<XX>(x)...){}

   template <typename...T>
   constexpr decltype(auto) operator()(T&&...t) const
   requires requires {this->invoke(std::index_sequence_for<X...>{}, std::forward<T>(t)...); }
   {
      return invoke(std::index_sequence_for<X...>{}, std::forward<T>(t)...);
   }

private:

   template <Entity FF, typename...T>
   static constexpr FF expand(FF&& f, T&&...)
   requires requires {std::forward<FF>(f);}
   {
      return std::forward<FF>(f);
   }

   template <Function FF, typename...T>
   static constexpr decltype(auto) expand(FF&& f, T&&...t)
   requires requires {f(std::forward<T>(t)...); }
   {
      return f(std::forward<T>(t)...);
   }

   template <Placeholder P, typename...T>
   static constexpr decltype(auto) expand(const P&, T&&...t)
   requires (PlaceholderIndex<P> < sizeof...(T))
   {
      return std::get<PlaceholderIndex<P>>(std::forward_as_tuple(std::forward<T>(t)...));
   }

   template <size_t...I, typename...T>
   constexpr decltype(auto) invoke(std::index_sequence<I...>, T&&...t) const
   requires requires {this->m_f(this->expand(std::get<I>(this->m_x), std::forward<T>(t)...)...);}
   {
      return m_f(expand(std::get<I>(m_x), std::forward<T>(t)...)...);
   }

private:
   F m_f{};
   std::tuple<X...> m_x;
};

template <Function F, typename...X>
Bind(F&&, X&&...) -> Bind<std::decay_t<F>, std::decay_t<X>...>;

} // namespace util


int main()
{
   using namespace std::placeholders;
   using util::Bind;

   constexpr auto make = [](auto&& t, auto&&...x) {
      std::ostringstream os;
      os << "{" << t;
      ((os << ", " << x), ...);
      os << "}";
      return os.str();
   };

   std::cout << Bind(make, make, Bind(make, make, 42, make), make)("A", 3.14) << std::endl;
   std::cout << Bind(make, _2, _3, _1, Bind(make, _2, _3, _1, _1, _3, _2), _1, _3, _2)("A", 42, 3.14) << std::endl;
}
Re[6]: Множественный форвардинг в std::bind
Здравствуйте, serg_joker, Вы писали:

_>Есть, где посмотреть в образовательных целях?


Всегда пожалуйста!

http://coliru.stacked-crooked.com/a/773ea192115f80cf

#include <concepts>
#include <functional>
#include <iostream>
#include <sstream>
#include <utility>

namespace util
{

template <typename...T>
struct Inherited : std::decay_t<T>... {};

template <typename> struct IsFreeFunction : std::false_type {};
template<typename R, typename...A> struct IsFreeFunction<R(A...)> : std::true_type {};
template <typename T> struct IsFreeFunction<T*> : IsFreeFunction<T> {};

template <typename T>
concept FreeFunction = IsFreeFunction<std::decay_t<T>>::value;

template <typename T>
concept FunctionObject =
std::is_class_v<std::decay_t<T>> &&
!requires { &Inherited < T, decltype([] {}) > ::operator(); };

template <typename T>
concept Function = FreeFunction<T> || FunctionObject<T>;

template <typename T>
concept Entity = !Function<T> && !std::same_as<T, void>;

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
using std::placeholders::_5;
using std::placeholders::_6;
using std::placeholders::_7;
using std::placeholders::_8;
using std::placeholders::_9;
using std::placeholders::_10;
using std::placeholders::_11;
using std::placeholders::_12;

template <typename> struct PlaceholderIndexTag;
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_1)>> : std::integral_constant<size_t, 0> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_2)>> : std::integral_constant<size_t, 1> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_3)>> : std::integral_constant<size_t, 2> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_4)>> : std::integral_constant<size_t, 3> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_5)>> : std::integral_constant<size_t, 4> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_6)>> : std::integral_constant<size_t, 5> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_7)>> : std::integral_constant<size_t, 6> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_8)>> : std::integral_constant<size_t, 7> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_9)>> : std::integral_constant<size_t, 8> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_10)>> : std::integral_constant<size_t, 9> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_11)>> : std::integral_constant<size_t, 10> {};
template <> struct PlaceholderIndexTag<std::decay_t<decltype(_12)>> : std::integral_constant<size_t, 11> {};

template <typename T>
concept Placeholder = (Entity<T> || Function<T>) && requires {
   PlaceholderIndexTag<std::decay_t<T>>::value;
};

template <Placeholder T>
inline constexpr size_t PlaceholderIndex = PlaceholderIndexTag<std::decay_t<T>>::value;

template <Function F, typename...X>
class Bind
{
public:
   constexpr Bind() = default;

   template <Function FF, typename...XX>
   constexpr Bind(FF&& f, XX&&...x) : m_f(std::forward<FF>(f)), m_x(std::forward<XX>(x)...){}

   template <typename...T>
   constexpr decltype(auto) operator()(T&&...t) const
   requires requires {this->invoke(std::index_sequence_for<X...>{}, std::forward<T>(t)...); }
   {
      return invoke(std::index_sequence_for<X...>{}, std::forward<T>(t)...);
   }

private:

   template <Entity FF, typename...T>
   static constexpr FF expand(FF&& f, T&&...)
   requires requires {std::forward<FF>(f);}
   {
      return std::forward<FF>(f);
   }

   template <Function FF, typename...T>
   static constexpr decltype(auto) expand(FF&& f, T&&...t)
   requires requires {f(std::forward<T>(t)...); }
   {
      return f(std::forward<T>(t)...);
   }

   template <Placeholder P, typename...T>
   static constexpr decltype(auto) expand(const P&, T&&...t)
   requires (PlaceholderIndex<P> < sizeof...(T))
   {
      return std::get<PlaceholderIndex<P>>(std::forward_as_tuple(std::forward<T>(t)...));
   }

   template <size_t...I, typename...T>
   constexpr decltype(auto) invoke(std::index_sequence<I...>, T&&...t) const
   requires requires {this->m_f(this->expand(std::get<I>(this->m_x), std::forward<T>(t)...)...);}
   {
      return m_f(expand(std::get<I>(m_x), std::forward<T>(t)...)...);
   }

private:
   F m_f{};
   std::tuple<X...> m_x;
};

template <Function F, typename...X>
Bind(F&&, X&&...) -> Bind<std::decay_t<F>, std::decay_t<X>...>;

} // namespace util


int main()
{
   using namespace std::placeholders;
   using util::Bind;

   constexpr auto make = [](auto&& t, auto&&...x) {
      std::ostringstream os;
      os << "{" << t;
      ((os << ", " << x), ...);
      os << "}";
      return os.str();
   };

   std::cout << Bind(make, make, Bind(make, make, 42, make), make)("A", 3.14) << std::endl;
   std::cout << Bind(make, _2, _3, _1, Bind(make, _2, _3, _1, _1, _3, _2), _1, _3, _2)("A", 42, 3.14) << std::endl;
}