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
相关产品推荐
相关产品推荐

