I ran into a bit of trouble with template operator overloads when entering namespaces. Consider addition of arrays:
// overloads.hpp
#include <array>
namespace mylib {
template <size_t N>
using DoubleArray = std::array<double,N>;
template <size_t N>
DoubleArray<N> operator+( const DoubleArray<N>& lhs, const DoubleArray<N>& rhs ) {return DoubleArray<N>();}
}
Testing this in namespace mylib
works as intended.
// test.cpp
#include "overloads.hpp"
namespace mylib {
void test()
{
DoubleArray<3> a({1.0,0.0,0.0});
DoubleArray<3> b({0.0,1.0,0.0});
DoubleArray<3> c(a+b); // <-- ok
}
}
Now suppose that I have a Complex
class in namespace mylib::mysublib
that has its own operator+
and a constructor from DoubleArray
(this constructor has to be explicit to prevent implicit conversion):
// nested.cpp
#include "overloads.hpp"
namespace mylib {
namespace mysublib {
struct Complex
{
Complex() {};
explicit Complex( const DoubleArray<2>& components );
DoubleArray<2> _components;
};
Complex operator+(const Complex& rhs, const Complex& lhs) {return Complex();}
void testNested()
{
DoubleArray<2> a({1.0,0.0});
DoubleArray<2> b({0.0,1.0});
DoubleArray<2> c(a+b); // <-- no match for ‘operator+’
DoubleArray<2> d( mylib::operator+(a,b) ); // <-- ok
}
}
}
Error message:
error: no match for ‘operator+’ (operand types are ‘mylib::DoubleArray<2> {aka std::array<double, 2>}’ and ‘mylib::DoubleArray<2> {aka std::array<double, 2>}’)
DoubleArray<2> c(a+b); // <-- no match for ‘operator+’
Why can't the overloaded operator be found when called from the nested namespace? The whole point of overloading (in this example) would be a clean syntax. Any ideas on how to get this working, or if it's even possible?
The operator+
of Complex
can be declared as friend
function in Complex
, which does not pollute the global namespace. Your example should compile after the following change.
struct Complex {
Complex(){};
explicit Complex(const DoubleArray<2>& components);
DoubleArray<2> _components;
friend Complex operator+(const Complex& rhs, const Complex& lhs) { return Complex(); }
};
According to C++ standard working draft N4140,
When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded.
In your case, the two operator+
functions are declared in different namespace and thus are not qualified for overload resolution.
When compiler finds the first match Complex operator+(const Complex& rhs, const Complex& lhs)
, DoubleArray
cannot be implicitly converted to Complex
. Therefore, you got the no match for ‘operator+’
error.