The following does not compile (with Clang 5.0.0 / gcc 7.3, std: C++11):
Error message in Clang:
error: invalid operands to binary expression (std::vector<double, std::allocator<double> >
and std::vector<double, std::allocator<double>>
)
#include <functional>
#include <vector>
namespace ns{
using MyType = std::vector<double>;
} // namespace ns
using ns::MyType;
MyType& operator+=( MyType& lhs, const MyType& rhs) {
for (int i = 0; i < lhs.size(); ++i) {
lhs[i] = lhs[i] + rhs[i];
}
return lhs;
}
MyType operator+( MyType lhs, const MyType& rhs) {
lhs += rhs;
return lhs;
}
namespace ns{
using Func = std::function<MyType()>;
Func operator+(
const Func &lhs, const Func &rhs) {
return [lhs, rhs]() {
auto y = lhs() + rhs(); // <-- error in this line
return y;
};
}
} // namespace ns
The compiler does not find the correct overload of operator+
. I do not understand why. The reason I define the operators outside the namespace is that ADL does not work for typedefs and using type aliases. What is the problem here? Why can't the compiler find operator+(MyType, const MyType &)
in the above circumstances?
All of the following alternatives do compile:
namespace ns {
MyType a, b;
auto c = a + b; // compiles
MyType f() {
MyType a_, b_;
return a_ + b_; // compiles
};
Func operator+(
const Func &lhs, const Func &rhs) {
return [lhs, rhs]() {
auto x = lhs();
x += rhs(); // <-- compiles; operator+= instead of operator+
return x;
};
}
} // namespace ns
Func operator+(
const Func &lhs, const Func &rhs) {
return [lhs, rhs]() {
auto y = lhs() + rhs(); // <-- no error if not in namespace ns
return y;
};
}
You are hiding the global namespace operator+
because you have defined an operator+
in the current scope. Unqualified name lookup keeps moving to the enclosing namespace until it has found at least one declaration. So because there is an operator+
in the current namespace, regardless of its argument list, name lookup does not proceed to search in the global namespace. See here for a detailed explanation of qualified lookup. The relevant bit is at the top.
For an unqualified name, that is a name that does not appear to the right of a scope resolution operator ::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
Note how both of these examples work. Only the changed segment is shown, the rest of your code must still be visible in order to compile.
namespace ns {
using Func = std::function<MyType()>;
using ::operator+;
Func operator+(
const Func &lhs, const Func &rhs) {
return [lhs, rhs]() {
auto y = lhs() + rhs();
return y;
};
}
} // namespace ns
operator+
namespace ns {
using Func = std::function<MyType()>;
Func func(
const Func &lhs, const Func &rhs) {
return [lhs, rhs]() {
auto y = lhs() + rhs();
return y;
};
}
} // namespace ns
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With