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

时间:2020-01-19 14:02:18

标签: c++ namespaces operator-overloading overload-resolution

输入名称空间时,模板运算符重载时遇到了一些麻烦。考虑添加数组:

// 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
}

}

现在假设我在命名空间Complex中有一个mylib::mysublib类,它有自己的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+’

为什么从嵌套名称空间调用时找不到重载运算符?重载的全部要点(在此示例中)将是一种简洁的语法。关于如何使其正常工作甚至可能的任何想法?

2 个答案:

答案 0 :(得分:1)

将您的第三个代码替换为

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

答案 1 :(得分:1)

X中可以将operator+的{​​{1}}声明为Complex函数,它不会污染全局名称空间。您的示例应在进行以下更改后编译。

friend

根据C++ standard working draft N4140

相同范围内为单个名称指定两个或多个不同的声明时,该名称被称为重载。

在您的情况下,两个Complex函数在不同的名称空间中声明,因此不符合重载解析的条件。

当编译器找到第一个匹配项struct Complex { Complex(){}; explicit Complex(const DoubleArray<2>& components); DoubleArray<2> _components; friend Complex operator+(const Complex& rhs, const Complex& lhs) { return Complex(); } }; 时,operator+无法隐式转换为Complex operator+(const Complex& rhs, const Complex& lhs)。因此,您遇到了DoubleArray错误。