Сообщение 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
Всегда пожалуйста!
_>Есть, где посмотреть в образовательных целях?
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
_>Есть, где посмотреть в образовательных целях?
Всегда пожалуйста!
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;
}