'g++ 11.2 cannot find an operator despite explicit using declaration
The following code fails to compile with g++ 11.2
#include <algorithm>
#include <array>
#include <utility>
#include <vector>
namespace tools {
template <std::size_t I = 0, class U, std::size_t N, class W, class F>
void op_1vec_impl(std::array<U, N>& a, const W& b, F&& f);
template <class U, std::size_t N, class W>
void operator/=(std::array<U, N>& a, const W& b) { op_1vec_impl(a, b, [](U& x, const W& y) { x /= y; }); }
// Implementation
template <std::size_t I, class U, std::size_t N, class W, class F>
void op_1vec_impl(std::array<U, N>& a, const W& b, F&& f)
{
f(std::get<I>(a), b);
if constexpr (I < (N - 1))
op_1vec_impl<I + 1>(a, b, std::forward<F>(f));
}
}
template <bool P>
void run();
int main(int argc, char *argv[])
{
run<false>();
return 0;
}
template <bool P>
void run()
{
std::vector<std::array<double, 80>> vec(100);
std::for_each(vec.begin(), vec.end(), [&](auto& el) { using tools::operator/=; el /= 4; });
}
Command line is:
g++ -c -std=c++17 -O3 -Wall -pedantic -o test_templates test_templates.cpp
The error is:
test_templates.cpp:41:89: error: no match for ‘operator/=’ (operand types are ‘std::array<double, 80>’ and ‘int’)
41 | std::for_each(vec.begin(), vec.end(), [&](auto& el) { using tools::operator/=; el /= 4; });
The code however compiles fine with g++ 10.1.x, and fails to compile from the version 11.? onwards. It also compiles with clang.
Test the code on godbolt.
Strangely, replacing the error line with
std::for_each(vec.begin(), vec.end(), [&](auto& el) { using namespace tools; el /= 4; });
the code compiles.
Even more strangely, the code compiles if I replace the subroutine run() with a non-template one as in the following code!
#include <algorithm>
#include <array>
#include <utility>
#include <vector>
namespace tools {
template <std::size_t I = 0, class U, std::size_t N, class W, class F>
void op_1vec_impl(std::array<U, N>& a, const W& b, F&& f);
template <class U, std::size_t N, class W>
void operator/=(std::array<U, N>& a, const W& b) { op_1vec_impl(a, b, [](U& x, const W& y) { x /= y; }); }
// Implementation
template <std::size_t I, class U, std::size_t N, class W, class F>
void op_1vec_impl(std::array<U, N>& a, const W& b, F&& f)
{
f(std::get<I>(a), b);
if constexpr (I < (N - 1))
op_1vec_impl<I + 1>(a, b, std::forward<F>(f));
}
}
void run();
int main(int argc, char *argv[])
{
run();
return 0;
}
void run()
{
std::vector<std::array<double, 80>> vec(100);
std::for_each(vec.begin(), vec.end(), [&](auto& el) { using tools::operator/=; el /= 4; });
}
All in all, it looks like a compiler bug, but is it really so?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
