Consider the following code snippet:
#include <functional>
namespace ns {
struct Arg{};
using Func = std::function<int(Arg)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, rhs](Arg arg) {
return lhs(arg) + rhs(arg);
};
}
}
int main() {
ns::Func foo = [](ns::Arg i) {return 5;};
ns::Func bar = [](ns::Arg i) {return 2;};
auto foobar = foo + bar;
return foobar(ns::Arg());
}
The above code compiles with various compilers. In contrast, the following code snippet does not compile. The only difference is the type of the argument used inside Func
(Arg
vs int
):
#include <functional>
namespace ns {
using Func = std::function<int(int)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, rhs](int i) {
return lhs(i) + rhs(i);
};
}
}
int main() {
ns::Func foo = [](int i) {return i + 5;};
ns::Func bar = [](int i) {return i * 2;};
auto foobar = foo + bar; // BANG! Error here!
return foobar(2);
}
I understand the error of the latter version: The called operator+
is defined in a namespace and thus not found without explicit specification of the namespace. Argument dependent lookup will not help here, because the operator+
is defined in a different namespace (ns
) than the type of the argument (std::function
is defined in namespace std
, the using
declaration is irrelevant for this).
But why is the correct operator+
found in the case where Func
takes an argument ns::Arg
? The namespace of Func
has not changed. Is the code using Arg
valid according to the C++ standard?