You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC 11.3.0使用using指令后仍无法匹配operator*=是否为Bug?

GCC 11.3.0中using tools::operator*=在Lambda内无法匹配运算符的问题

这段代码在GCC 11.3.0下编译失败,但在GCC 13.1.1中可以正常编译。代码中已经在Lambda内通过using tools::operator*=引入了自定义的operator*=模板,却依然无法匹配std::array<int, N>与int的乘法赋值操作,而显式调用tools::operator*=(el, rhs)则可以正常编译。

重现代码

#include <array>
#include <memory>
#include <tuple>

namespace tools {
  template <typename U, typename W, std::size_t N>
  void operator*=(std::array<U, N>& a, const W& b) {
    for (auto& x : a)
      x *= b;
  }
}

namespace nameA {
  template <typename Jclass>
  struct Abase {
    
    template <typename... U>
    void calc(const typename Jclass::Utype& v, typename Jclass::Wtype& out, std::tuple<U...> par) const;
  };

  template <typename Jclass>
  template <typename... U>
  void Abase<Jclass>::calc(const typename Jclass::Utype& v, typename Jclass::Wtype& out, std::tuple<U...> par) const
  {
    std::unique_ptr<Jclass> j{new Jclass};
    std::apply([&](auto&&...x) { return j->calc(v, out, x...); }, par);
  }
}

template <std::size_t N, std::size_t M>
struct outtype {
  std::array<int, N> a;
  std::array<int, M> b;

private:
  template <class F, class... ArgsType>
  void doall(F&& f, ArgsType... args) { f(a, std::forward<ArgsType>(args)...); f(b, std::forward<ArgsType>(args)...); }

public:
  void operator*=(int rhs) { doall([&](auto& el) { using tools::operator*=; el *= rhs; }); }
};

namespace nameA {
  template <typename U, typename W>
  struct Jbase {
    using Utype = U;
    using Wtype = W;
    template <typename D>
    void calc(const U& in, W& out, const D& d) const
    {
      f(in, out);
      out *= d;
    }
    virtual void f(const U& in, W& out) const = 0;
  };
}

struct J : public nameA::Jbase<std::array<int, 3>, outtype<3, 3>> {
  virtual void f(const std::array<int, 3>& in, outtype<3, 3>& out) const { out.a = in; out.b = in; }
};


int main()
{
  nameA::Abase<J> a;
  std::array<int, 3> in = { 1, 2, 3 };
  outtype<3, 3> out;
  a.calc(in, out, std::make_tuple(4));
}

编译命令

g++ -Wall -pedantic -std=c++17 -o test test.cpp

错误信息

test.cpp:40:80: error: no match for ‘operator*=’ (operand types are ‘std::array<int, 3>’ and ‘int’)
   40 |   void operator*=(int rhs) { doall([&](auto& el) { using tools::operator*=; el *= rhs; }); }

分析与结论

这确实是GCC 11.3.0的编译器Bug,属于模板上下文(尤其是Lambda的auto参数)中using声明引入的运算符重载无法被正确解析的问题:

  • 当使用using tools::operator*=时,GCC 11.x未能正确将该重载纳入el *= rhs的候选匹配列表,尽管语法上这完全符合C++标准。
  • 显式调用tools::operator*=(el, rhs)绕过了重载解析的问题,直接指定调用目标模板,因此可以编译通过。
  • GCC 13.1.1已经修复了该问题,说明这是编译器在模板重载解析逻辑上的历史缺陷。

内容的提问来源于stack exchange,提问作者francesco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:34:56