std::plus 的模板推导失败

fra*_*sco 5 c++ templates

以下代码定义了任意类型的operator+between std::array。该实现包括定义一个辅助例程op2,该例程采用通用可调用运算符,并通过模板递归将其应用于数组的每个元素。

#include <array>
#include <functional>
#include <iostream>

template <typename T, std::size_t N>
std::array<T, N> operator+(const std::array<T, N>& lhs, const std::array<T, N>& rhs);

template <std::size_t Index = 0, typename T, std::size_t N, class F>
void op2(const std::array<T, N>& lhs, const std::array<T, N>& rhs, std::array<T, N>& res, F&& op);

template <typename T, std::size_t N>
std::array<T, N> operator+(const std::array<T, N>& lhs, const std::array<T, N>& rhs)
{
    std::array<T, N> res;
    op2(lhs, rhs, res, std::plus{});
    return res;
}

template <std::size_t Index, typename T, std::size_t N, class F>
void op2(const std::array<T, N>& lhs, const std::array<T, N>& rhs, std::array<T, N>& res, F&& op)
{
    std::get<Index>(res) = op(std::get<Index>(lhs), std::get<Index>(rhs));
    if constexpr (Index < (N - 1))
        op2<Index + 1>(lhs, rhs, res, std::forward<F>(op));
}


template <std::size_t N>
void print_array(const std::array<int, N>& a)
{
    for (int x : a)
        std::cout << x << ' ';
    std::cout << '\n';
}

int main(){
    std::array<int, 3> a{1, 2, 3};
    std::array<int, 3> b{2, 2, 1};
    
    print_array(a + b);

    std::array<std::array<int, 3>, 2> c{a, b};
    std::array<std::array<int, 3>, 2> d{a, b};
    
    auto x = c + d; // Error: no match for call to std::plus<void>


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

看到它住在Coliru

第一部分工作正常并计算 inta和数组的总和b

接下来,cdstd::arraystd::array<int,3>。程序无法编译,因为它无法std::plusc和 的组件之间找到匹配项d,即std::plus::operator()无法理解如何对 2 求和std::array<int, 3>

一种解决方法是定义operator+

template <typename T, std::size_t N>
std::array<T, N> operator+(const std::array<T, N>& lhs, const std::array<T, N>& rhs)
{
    std::array<T, N> res;
    op2(lhs, rhs, res, [](const auto& lhs, const auto& rhs) { return lhs + rhs; });
    return res;
}
Run Code Online (Sandbox Code Playgroud)

看到它住在Coliru

根据引用 std::plus=std::plus<void>应该简单地返回带有参数和返回类型推导的总和结果,与匿名 lambda 所做的非常相似。

为什么用的解决方案std::plus不编译?