名称空间中模板运算符的重载解析

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();} 隐藏了预期的运算符

Complexoperator+可以声明为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+’ 错误。