So I'm writing operator<< overload for a class as following:
#test.hh
#pragma once
#include<iostream>
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;
}
Testing with following main:
#main.cc
#include"./test.hh"
#include<iostream>
int main() {
    ns::test a(12);
    std::cout << a << std::endl;
    return 0;
}
Which when compiled with g++ test.cc main.cc gave back error:
/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
Apparently the compiler resolves the function to ns::operator<< when it should be calling operator<<. I understand that C++ will find function within the namespace of argument, but did I implement the operator overloading incorrectly? Answers like this seems to have same implementation like me, which the only difference is they all wrote them in header.
Which part did I do wrong? And how could I fix such issue?
 
     
    