C++类外运算符实现解析为`namespace::operator<<`而不是`operator<<`。

23 浏览
0 Comments

C++类外运算符实现解析为`namespace::operator<<`而不是`operator<<`。

所以我正在为一个类写operator<<重载,如下所示:

#test.hh
#pragma once
#include
namespace ns {
    struct test {
        double d;
        test(double x): d(x) {}
        friend std::ostream& operator<<(std::ostream&, const test&);
    };
}

#test.cc
#include"./test.hh"
std::ostream& operator<<(std::ostream& os, const ns::test& a) {
    os << a.d;
    return os;
}

使用以下主函数进行测试:

#main.cc
#include"./test.hh"
#include
int main() {
    ns::test a(12);
    std::cout << a << std::endl;
    return 0;
}

当使用g++ test.cc main.cc编译时,会返回以下错误:

/usr/sbin/ld: /tmp/cc6Rs93V.o: in function `main':                                                      
main.cc:(.text+0x41): undefined reference to `ns::operator<<(std::ostream&, ns::test const&)'           
collect2: error: ld returned 1 exit status

显然,编译器将函数解析为ns::operator<<,而应该调用operator<<。我知道C++会在参数的命名空间中查找函数,但我是否错误地实现了运算符重载?像这样的答案似乎像我一样实现了相同的内容,唯一的区别是它们都在头文件中编写。

我哪里做错了?如何解决此类问题?

admin 更改状态以发布 2023年5月21日
0
0 Comments

编译器使用参数相关查找 (ADL)。由于运算符的第二个操作数具有在名字空间ns中声明的类型说明符test,因此编译器还会在test类的定义和声明该类的名字空间ns中查找该运算符。虽然该运算符的声明位于test类的作用域内,但其未定义,因此编译器会发出错误。

如果您定义了该运算符,则编译器会发出另一个错误,即定义了两个运算符并且存在歧义。

0
0 Comments

这是我针对像这种情况的解决方案:

#include
namespace ns 
{
    struct test 
    {
        double d;
        test(double x) : d(x) {}
        friend std::ostream& operator<<(std::ostream&, const test&);
    };
    std::ostream& operator<<(std::ostream& os, const ns::test& a) {
        os << a.d;
        return os;
    }
}
int main() 
{
    ns::test a(12);
    std::cout << a << std::endl;
    return 0;
}

0