с 17 руководство дедукции шаблон для частичной специализации - возможно?


Предположим, я объявляю класс объекты функций определенного арность (количество параметров), которые могут быть между 0 и аргументы арности уже встроен.

Вот пример условной 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;}

Теперь я хочу обобщить эту идею, и позволить спецификацию 'арность (количество смысловых аргументов) в качестве аргумента шаблона.

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

Можно ли написать руководство по вычету на такой частичной специализации?