假设我声明了一个给定arity(参数个数)的函数对象类,它可能介于0和arity参数之间。
这是一个名义上的binary_op的例子,请注意模板推导指南,它允许轻松使用这些功能对象。
#include <tuple>
#include <utility>
#include <iostream>
template<class Pred, class...ArgsR>
struct binary_op
{
static_assert(sizeof...(ArgsR) <= 2, "binary ops can have max 2 args");
template<class P, class...As>
binary_op(P&& p, As&&...as)
: pred_(std::forward<P>(p))
, args_r(std::forward<As>(as)...)
{}
template<class...ArgsL>
decltype(auto) operator()(ArgsL&&...args_l) const
{
static_assert(sizeof...(ArgsR) + sizeof...(ArgsL) == 2,
"binary ops must be executed with 2 args");
return std::apply(pred_, std::tuple_cat(std::tie(args_l...), args_r));
}
Pred pred_;
std::tuple<ArgsR...> args_r;
};
template<class Pred, class...ArgsR> binary_op(Pred&&, ArgsR&&...) -> binary_op<std::decay_t<Pred>, std::decay_t<ArgsR>...>;
int main()
{
auto plus_op = [](auto&& x, auto&& y) -> decltype(auto) { return x + y; };
auto plus = binary_op(plus_op);
auto plus2 = binary_op(plus_op, 2);
auto plus2_3 = binary_op(plus_op, 2, 3);
std::cout << plus(3, 5) << std::endl;
std::cout << plus2(5) << std::endl;
std::cout << plus2_3() << std::endl;
}
现在我想概括一下这个想法,并允许规范&#39; arity&#39; (名义参数的数量)作为模板参数。
我第一次尝试为部分特化编写一个演绎指南(未指定Arity模板参数)并不成功,所以我使用了一个未使用的arity<N>
构造函数参数:
#include <tuple>
#include <utility>
#include <iostream>
template<std::size_t N>
struct arity : std::integral_constant<std::size_t, N> {};
template<std::size_t Arity, class Pred, class...ArgsR>
struct arity_op
{
using overall_arity = std::integral_constant<std::size_t, Arity>;
static_assert(sizeof...(ArgsR) <= overall_arity(), "number of initial args must be less than or equal to arity");
using function_arity = std::integral_constant<std::size_t, overall_arity() - sizeof...(ArgsR)>;
template<class P, class...As>
arity_op(arity<Arity>, P&& p, As&&...as)
: pred_(std::forward<P>(p))
, args_r(std::forward<As>(as)...)
{}
template<class...ArgsL>
decltype(auto) operator()(ArgsL&&...args_l) const&
{
static_assert(sizeof...(ArgsL) == function_arity(),
"arguments to functor must have correct arity");
return std::apply(pred_,
std::tuple_cat(std::forward_as_tuple(args_l...),
args_r));
}
Pred pred_;
std::tuple<ArgsR...> args_r;
};
template<std::size_t Arity, class Pred, class...ArgsR> arity_op(arity<Arity>, Pred&&, ArgsR&&...) -> arity_op<Arity, std::decay_t<Pred>, std::decay_t<ArgsR>...>;
int main()
{
auto plus_op = [](auto&& x, auto&& y) -> decltype(auto) { return x + y; };
auto plus = arity_op(arity<2>(), plus_op);
static_assert(decltype(plus)::function_arity() == 2, "");
auto plus2 = arity_op(arity<2>(), plus_op, 2);
static_assert(decltype(plus2)::function_arity() == 1, "");
auto plus2_3 = arity_op(arity<2>(), plus_op, 2, 3);
static_assert(decltype(plus2_3)::function_arity() == 0, "");
std::cout << plus(3, 5) << std::endl;
std::cout << plus2(5) << std::endl;
std::cout << plus2_3() << std::endl;
}
我想我想要的是能够写下:
auto plus = arity_op<2>(plus_op); // arity specified as a template argument
是否可以为这种部分专业化写一个演绎指南?