名称空间中模板运算符的重载解析
Overload resolution for template operators in namespaces
我 运行 在进入命名空间时遇到模板运算符重载的一些麻烦。考虑添加数组:
// 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>();}
}
在 namespace mylib
中测试它按预期工作。
// 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
}
}
现在假设我在命名空间 mylib::mysublib
中有一个 Complex
class,它有自己的 operator+
和一个来自 DoubleArray
的构造函数(这个构造函数有要显式以防止隐式转换):
// 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: 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+’
为什么从嵌套命名空间调用时找不到重载运算符?重载的全部意义(在这个例子中)将是一个干净的语法。关于如何让它工作的任何想法,或者它是否可能?
将您的第三个代码替换为
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
}
}
}
,然后编译。
定义 Complex operator+(const Complex& rhs, const Complex& lhs) {return Complex();}
隐藏了预期的运算符
Complex
的operator+
可以声明为Complex
中的friend
函数,不会污染全局命名空间。您的示例应在以下更改后编译。
struct Complex {
Complex(){};
explicit Complex(const DoubleArray<2>& components);
DoubleArray<2> _components;
friend Complex operator+(const Complex& rhs, const Complex& lhs) { return Complex(); }
};
根据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.
在您的例子中,两个 operator+
函数是在不同的命名空间中声明的,因此不符合重载解析的条件。
当编译器找到第一个匹配项 Complex operator+(const Complex& rhs, const Complex& lhs)
时,DoubleArray
无法隐式转换为 Complex
。因此,您得到了 no match for ‘operator+’
错误。
我 运行 在进入命名空间时遇到模板运算符重载的一些麻烦。考虑添加数组:
// 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>();}
}
在 namespace mylib
中测试它按预期工作。
// 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
}
}
现在假设我在命名空间 mylib::mysublib
中有一个 Complex
class,它有自己的 operator+
和一个来自 DoubleArray
的构造函数(这个构造函数有要显式以防止隐式转换):
// 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: 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+’
为什么从嵌套命名空间调用时找不到重载运算符?重载的全部意义(在这个例子中)将是一个干净的语法。关于如何让它工作的任何想法,或者它是否可能?
将您的第三个代码替换为
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
}
}
}
,然后编译。
定义 Complex operator+(const Complex& rhs, const Complex& lhs) {return Complex();}
隐藏了预期的运算符
Complex
的operator+
可以声明为Complex
中的friend
函数,不会污染全局命名空间。您的示例应在以下更改后编译。
struct Complex {
Complex(){};
explicit Complex(const DoubleArray<2>& components);
DoubleArray<2> _components;
friend Complex operator+(const Complex& rhs, const Complex& lhs) { return Complex(); }
};
根据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.
在您的例子中,两个 operator+
函数是在不同的命名空间中声明的,因此不符合重载解析的条件。
当编译器找到第一个匹配项 Complex operator+(const Complex& rhs, const Complex& lhs)
时,DoubleArray
无法隐式转换为 Complex
。因此,您得到了 no match for ‘operator+’
错误。