Searching for the title of this question gives me a number of people quoting the same error, but under different circumstances, and unfortunately the answers there provided are specific to their situation, and I do not see how they can help me.
I am trying to overload operator<<
for a template class. Following is a test case:
Vector.h:
#ifndef __INCL_VECTOR_H__
#define __INCL_VECTOR_H__
#include <array>
template < class T, unsigned int N >
class Vector
{
public:
Vector();
Vector( std::array< T, N > );
template < class U, unsigned int M > friend Vector< U, M > operator+ ( const Vector< U, M >&, const Vector< U, M >& );
template < class U, unsigned int M > friend std::ostream& operator<< ( std::ostream&, Vector< U, M >& );
T& operator[] ( const unsigned int& );
protected:
std::array< T, N > _values;
};
#include "Vector.hpp"
#endif
Vector.hpp:
#include "Vector.h"
#include <iostream>
template < class T, unsigned int N >
Vector< T, N >::Vector()
{
}
template < class T, unsigned int N >
Vector< T, N >::Vector( std::array< T, N > otherArray )
{
_values = *( new std::array< T, N >( otherArray ) );
}
template < class U, unsigned int M >
Vector< U, M > operator+ ( const Vector< U, M > &lhVector, const Vector< U, M > &rhVector )
{
Vector< U, M > sumVector;
for( unsigned int i = 0; i < M; i++ )
sumVector[i] = lhVector[i] + rhVector[i];
return sumVector;
}
template < class U, unsigned int M >
std::ostream& operator<< ( std::ostream &out, Vector< U, M > &cVector )
{
out << "< ";
for( int i = M - 1; i >= 0; i-- )
{
out << cVector[i];
if( i )
out << ", ";
}
out << " >";
return out;
}
template < class T, unsigned int N >
T& Vector< T, N >::operator[] ( const unsigned int &index )
{
return _values[ index ];
}
vectorTest.cpp:
#include "Vector.h"
#include <iostream>
#include <array>
using namespace std;
int main( int argc, char* argv[] )
{
Vector< int, 3 > u( array< int, 3 > { 1, 4, 2 } );
Vector< int, 3 > v( array< int, 3 > { -2, 3, -1 } );
cout << "u = " << u << endl;
cout << "v = " << v << endl;
cout << "u + v = " << u + v << endl;
return 0;
}
The line which causes the error is cout << "u + v = " << u + v << endl;
; the previous two lines work as expected.
The error message is as follows (compiling as g++ -std=c++11 Vector.h vectorTest.cpp
):
vectorTest.cpp: In function ‘int main(int, char**)’:
vectorTest.cpp:15:31: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
In file included from /usr/include/c++/4.7/iostream:40:0,
from Vector.hpp:2,
from Vector.h:34:
/usr/include/c++/4.7/ostream:600:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Vector<int, 3u>]’
In file included from Vector.h:34:0:
Vector.hpp: In instantiation of ‘Vector<U, M> operator+(const Vector<U, M>&, const Vector<U, M>&) [with U = int; unsigned int M = 3u]’:
vectorTest.cpp:15:31: required from here
Vector.hpp:40:9: error: passing ‘const Vector<int, 3u>’ as ‘this’ argument of ‘T& Vector<T, N>::operator[](const unsigned int&) [with T = int; unsigned int N = 3u]’ discards qualifiers [-fpermissive]
Vector.hpp:40:9: error: passing ‘const Vector<int, 3u>’ as ‘this’ argument of ‘T& Vector<T, N>::operator[](const unsigned int&) [with T = int; unsigned int N = 3u]’ discards qualifiers [-fpermissive]
I'm unable to understand what these error messages are telling me. I'd appreciate any assistance.
Change this:
to this:
The compiler is telling you that C++ will not let you bind a temporary
Vector
such asu + v
to a non-constVector&
.And you don't modify that
Vector
, so it should beconst
to begin with.FIRST PROBLEM:
To make your program compile, just use an lvalue reference to
const
as the second parameter of youroperator <<
(both in thefriend
-declaration and in the definition of that function):The reason why your program won't compile is that your overload of
operator <<
accepts an lvalue reference to non-const
as its second argument, and lvalue references to non-const
cannot bind to rvalues.Since the result of
operator +
between two instances ofVector
is a temporary, and a temporary is an rvalue, the compiler can't invoke youroperator <<
, and is therefore unable to resolve the call.SECOND PROBLEM:
Once you fixed the above issue, you'll have to solve a second one: your
Vector
class template does not provide aconst
version ofoperator []
, so your rewrittenoperator <<
, which now accepts a reference to aconst
vector, won't be able to access the vector's elements.And of course the corresponding definition: