std::inner_product 不使用特定的 std::vector + 和 * 运算符重载进行编译

std::inner_product doesn't compile with specific std::vector + and * operator overloads

提问人:Vernon Gutierrez 提问时间:12/14/2021 更新时间:12/14/2021 访问量:271

问:

我正在尝试用 C++ 编写一个小型线性代数库,纯粹用于教育目的。我选择尽可能多地使用标准库来最大限度地提高我的学习效果。我正在尝试使用 .(矩阵按列优先顺序排列)。std::inner_product

我有以下代码,它不能在最新版本的 GCC(撰写本文时为 11.1.0)中编译:

#include <algorithm>
#include <functional>
#include <numeric>
#include <vector>
using namespace std;

// copy-pasted from <numeric>, but changed identifier
template<typename _InputIterator1, typename _InputIterator2, typename _Tp>
    inline _Tp
    inner_product2(_InputIterator1 __first1, _InputIterator1 __last1,
          _InputIterator2 __first2, _Tp __init)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
      __glibcxx_requires_valid_range(__first1, __last1);

      for (; __first1 != __last1; ++__first1, (void)++__first2)
    __init = __init + (*__first1 * *__first2);
      return __init;
    }

struct custom_int {
    int x;
    custom_int(): x(0) {}
    custom_int(int x): x(x) {}
    custom_int& operator+=(const custom_int& y) { x += y.x; return *this; }
    custom_int& operator*=(const custom_int& y) { x *= y.x; return *this; }
};
using int_t = int;
vector<int_t> operator+(vector<int_t> u, const vector<int_t>& v) {
    for(int i = 0; i < v.size(); i++) {
        u[i] += v[i];
    }
    return u;
}
vector<int_t> operator*(vector<int_t> v, const int_t& scalar) { 
    for(auto& vi : v) {
        vi *= scalar;
    }
    return v;
}
int main() {
    vector<vector<int_t>> A = {{2, 1, 0}, {-1, 0, 0}, {1, 0, 1}};
    vector<int_t> b = {3, 2, 2};
    inner_product(A.begin(), A.end(), b.begin(), vector<int_t>(A[0].size()));
    return 0;
}

但是,执行下列操作之一会使其编译:

  1. 更改为 .using int_t = int;using int_t = custom_int;
  2. 更改为inner_product(A.begin(), A.end(), b.begin(), vector<int_t>(A[0].size()));inner_product2(A.begin(), A.end(), b.begin(), vector<int_t>(A[0].size()));

为什么会这样?

C++ GCC 向量 运算符重载 std

评论

2赞 Daniel Langr 12/14/2021
可能存在一些与命名空间相关的问题。IIRC,运算符通常应在其操作数类型相同的命名空间中定义。但是,在您的例子中,您对操作数的行为是在命名空间之外定义的。此问题的现场演示:godbolt.org/z/K9E4chKMqoperator+std::vectorstd
1赞 463035818_is_not_an_ai 12/14/2021
这是 stackoverflow.com/q/70289006/4117728 的相同问题。不幸的是,重复项并不容易找到。我避免这个问题的经验法则是:不要为你不拥有的类型重载运算符。在这里,您可以将 与 as 成员一起使用,该成员可根据需要实现运算符my_vectorstd::vector
4赞 Peter 12/14/2021
您知道有一个变体可以接受两个额外的参数吗?- 一个是表示加法的函数对象,另一个是表示乘法的函数对象。您可能可以以某种方式使用它,而不是修改不接受这些参数的(特定于编译器的)实现。std::inner_product()std::inner_product()
0赞 Vernon Gutierrez 12/14/2021
谢谢你的评论。我想我现在明白了。@463035818_is_not_a_number链接的重复问题使我找到了 en.cppreference.com/w/cpp/language/adl,我应该阅读它以了解为什么当 的类型参数是自定义时它会起作用。std::vector
0赞 Vernon Gutierrez 12/14/2021
@Peter我希望使依赖的操作员超载就足够了。(无论如何,这些重载对其他目的都很有用。我不打算修改特定于编译器的实现。它只是为了证明我对“重载运算符时命名空间很重要”的无知。哦,好吧,我想我必须走一条更迂回的道路。不过好建议。std::inner_product

答: 暂无答案