I've run into some strange linkage problems with gcc (and MSVC) with regards to finding an overloaded stream operator in a C++ library I created. The gist of it is very simple, I have a class called gpumat. This class overloads the << operator like this:
Code:
class gpumat {
/* stuff */
} ;
std::ostream& operator<<(std::ostream& output, const gpumat & p) // print a gpumat
{
/* implementation */
}
/* ..... usage */
using namespace std ;
gpumat g(3,4) ;
g.cgauss()
cout << g << endl ;
Note the const identifier before the &p input argument.
For gcc the linker will fail with something like:
undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, gpumat&)'.
This is baffling to me since it's perfectly legal to pass a non const. variable into a function that has a const specifier. The const is supposed to mean that the function will not change it's input. Moreover if I wanted to print a temporary computation, the const declaration is required as I understand it, ie:
Code:
gpumat a, b ;
/* initialization */
cout << a + b << endl ;
Microsoft's cl.exe will fail to link if you do not have the const specifier in front of &p if you pass a temporary class into the << operator (or any other overloaded function actually).
If I remove the const token gcc compiles links and runs my code just fine.
Code:
class gpumat {
/* stuff */
} ;
std::ostream& operator<<(std::ostream& output, gpumat & p) // print a gpumat
{
/* implementation */
}
/* ..... usage */
using namespace std ;
gpumat g(3,4) ;
g.cgauss()
cout << g << endl ;
How can this be correct? If it is one would have to supply const and non const versions of every overloaded function/operator for each argument and it would remove any optimization advantage since the non-constant version would be linked in for most usage patterns.