I am writing a small matrix library in C++ for matrix operations. However my compiler complains, where before it did not. This code was left on a shelf for 6 months and in between I upgraded my computer from debian etch to lenny (g++ (Debian 4.3.2-1.1) 4.3.2
) however I have the same problem on a Ubuntu system with the same g++.
Here is the relevant part of my matrix class:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
}
}
And the "implementation":
using namespace Math;
std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {
[...]
}
This is the error given by the compiler:
matrix.cpp:459: error: 'std::ostream&
Math::Matrix::operator<<(std::ostream&,
const Math::Matrix&)' must take
exactly one argument
I'm a bit confused by this error, but then again my C++ has gotten a bit rusty after doing lots of Java those 6 months. :-)
Just telling you about one other possibility: I like using friend definitions for that:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
[...]
}
};
}
The function will be automatically targeted into the surrounding namespace Math (even though its definition appears within the scope of that class) but will not be visible unless you call operator<< with a Matrix object which will make argument dependent lookup find that operator definition. That can sometimes help with ambiguous calls, since it's invisible for argument types other than Matrix. When writing its definition, you can also refer directly to names defined in Matrix and to Matrix itself, without qualifying the name with some possibly long prefix and providing template parameters like Math::Matrix<TypeA, N>.
You have declared your function as friend. It's not a member of the class. You should remove Matrix:: from the implementation. friend means that the specified function (which is not a member of the class) can access private member variables. The way you implemented the function is like an instance method for Matrix class which is wrong.
To add to Mehrdad answer ,
namespace Math
{
class Matrix
{
public:
[...]
}
std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}
In your implementation
std::ostream& operator<<(std::ostream& stream,
const Math::Matrix& matrix) {
matrix.print(stream); //assuming you define print for matrix
return stream;
}
Assuming that we're talking about overloading operator << for all classes derived from std::ostream to handle the Matrix class (and not overloading << for Matrix class), it makes more sense to declare the overload function outside the Math namespace in the header.
Use a friend function only if the functionality cannot be achieved via the public interfaces.
Matrix.h
namespace Math {
class Matrix {
//...
};
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);
Note that the operator overload is declared outside the namespace.
Matrix.cpp
using namespace Math;
using namespace std;
ostream& operator<< (ostream& os, const Matrix& obj) {
os << obj.getXYZ() << obj.getABC() << '\n';
return os;
}
On the other hand, if your overload function does need to be made a friend i.e. needs access to private and protected members.
Math.h
namespace Math {
class Matrix {
public:
friend std::ostream& operator<<(std::ostream&, const Matrix&);
};
}
You need to enclose the function definition with a namespace block instead of just using namespace Math;.
Matrix.cpp
using namespace Math;
using namespace std;
namespace Math {
ostream& operator<<(ostream& os, const Matrix& obj) {
os << obj.XYZ << obj.ABC << '\n';
return os;
}
}
In C++14 you can use the following template to print any object which has a T::print(std::ostream&)const; member.
template<class T>
auto operator<<(std::ostream& os, T const & t) -> decltype(t.print(os), os)
{
t.print(os);
return os;
}
In C++20 Concepts can be used.
template<typename T>
concept Printable = requires(std::ostream& os, T const & t) {
{ t.print(os) };
};
template<Printable T>
std::ostream& operator<<(std::ostream& os, const T& t) {
t.print(os);
return os;
}
I would like to simplify this a little with an example that overloads << to print an array.
First pass both the object types around the << operator
create a function to overload the operator as follows.
#include<iostream>
using namespace std;
void operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
os << arr[i] << " ";
}
os << endl;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << arr;
}
if cascading of operators is also required make sure to return cout object
in the overloaded function as follows,
#include<iostream>
using namespace std;
ostream& operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
return os;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 11,22,33,44,55,66,77,88,99,100 };
// cascading of operators
cout << arr << arr2;
}
Related
The following code does not compile:
#include <type_traits>
#include <optional>
#include <iostream>
using namespace std;
namespace dbj {
template< typename K, typename V >
class top final {
static_assert(
! is_same_v<K,V>,
" to make things simpler K and V must be different types"
);
public:
// nested type names
using key_type = optional<K>;
using val_type = optional<V>;
using type = top;
private:
key_type key_{};
val_type val_{};
public:
top() = delete;
explicit top(K k, V v) : key_(k), val_(v) {}
private:
// PROBLEM A: not found by
// friend wostream & operator << (wostream & os, type top_)
friend wostream & operator << (wostream & os, key_type key_arg_ ) {
return os << L"\nK : " << key_arg_.value_or(K{});
}
// PROBLEM B: not found by
// friend wostream & operator << (wostream & os, type top_)
friend wostream & operator << ( wostream & os, val_type val_arg_ ) {
return os << L"\nV : " << val_arg_.value_or(V{});
}
// found no problem
friend wostream & operator << (wostream & os, type top_)
{
// ISSUE D: this is not looking for overloads in the immediate scope
// i.e. inside the template class
// this is first looking for operator declaration inside namespace dbj
return os << L"\n\nprinting dbj::top<K,V> : " << top_.key_ << L"," << top_.val_;
}
}; // top
} // dbj ns
using top_type = dbj::top<wstring, int>;
extern "C" int test_operator_overloading_puzzle()
{
top_type top_{ L"the key", 42 };
std::wcout << top_ << std::endl;
return 1;
}
Also available here: https://wandbox.org/permlink/jMKpn6CKFL2cyceO
Every compiler complains that within the streaming operator for type top_, no match is found for streaming top_.key (marked ISSUE D in the code above). Why can't lookup find the two streaming functions I declared directly above them?
Here's a simpler reproduction:
namespace A {
struct X { };
}
namespace B {
struct Y {
A::X x;
// #1
friend std::ostream& operator<<(std::ostream& os, A::X) {
return os;
}
// #2
friend std::ostream& operator<<(std::ostream& os, Y y) {
return os << y.x; // error: no match for operator<<
}
};
}
This is because of how name lookup works. When you declare and define a namespace-scope friend function like this, that function can only be found by argument-dependent lookup of its arguments. It is never found by regular unqualified lookup.
But the function you're declaring in #1 isn't actually in the associated namespace of any of its arguments - the function is declared in namespace B, but its two arguments are in namespace std and namespace A, respectively. As a result, when we write os << y.x, no matching candidates are found by regular unqualified lookup and then no candidates are found by argument-dependent lookup either - #1 is not in the right namespace. Hence, no candidates.
The shortest solution is to just add a namespace-scope declaration of #1 outside of struct Y:
namespace B {
std::ostream& operator<<(std::ostream&, A::X);
struct Y { ... };
}
Now, this function can be found by regular unqualified lookup, so the call in #2 works. But really, there's no reason to have declared #1 as a friend function with B::Y (it in no way refers to B::Y), so just declare it externally. It also doesn't work very well as a streaming operator, so probably just make it a regular function instead.
Just building on top of Barry's simplification of the question and then on top of his answer.
namespace {
using namespace std;
namespace A {
struct X {
// #1 --> SOLUTION to problem #1
// friend operator is here in the scope where
// name lookup can find it, declared and defined
friend wostream& operator<<(wostream& os, X) {
return os << L"A::X" ;
}
};
}
namespace B {
struct Y {
A::X x;
// #1 --> PROBLEM: name lookup can not find this
// as it is in the scope unrelated to A::X
/*
friend std::ostream& operator<<(std::ostream& os, A::X) {
return os;
}
*/
// #2
friend wostream& operator<<(wostream& os, Y y) {
// << y.x is normally found inside the
// type of x and that is A::X
return os << L"\nB::Y --> " << y.x;
}
};
}
void test_barry() {
B::Y by_;
wcout << by_;
}
}
This is for the situations when we can insert the necessary friend operator inside the nested type. Otherwise please see Barry's answer.
For further education opportunity perhaps this is a good start.
I would like to define an ostream operator to let me easily output variables of type alglib::complex. To provide a working example without including the alglib library I'll instead overload the output of complex<double> below (this clarification because of an earlier version of the question). In the header file "my_class.h" I have
using namespace std;
#include <complex>
#include <iostream>
class my_class {
public:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
void output(complex<double>);
my_class() {}
~my_class() {}
};
And in the source file "my_class.cpp" I have
#include "my_class.h"
void my_class::output(complex<double> cd) {
cout << cd << endl;
}
Finally I have a main method file "run_my_class.cpp":
#include "my_class.h"
int main(int argc, const char* argv[]) {
my_class obj;
complex<double> cd=complex<double>(1.0,-1.0);
obj.output(cd);
}
I try to compile using
g++ -c my_class.cpp
but this gives me the error
my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument
ostream& operator << (std::ostream& os, complex<double> a) {
However, if I define the operator as a friend, namely friend ostream& operator << (std::ostream& os, complex<double> a), it compiles and I compile the main method:
g++ run_my_class.cpp my_class.o -o run_my_class
And it works as it should. However this is not what it seems the friend keyword is for. Is there a better way to make this work?
Since operator << will be called on an std::ostream, you cannot define this procedure as a member function for my_class, you have to define it as a global function, since it's an operation for std::ostream, not my_class.
By putting the friend keyword into the declaration, you are saying that you want to declare the operator << as a friend global function (not a member function!). The C++ standard lets you put the definition of the friend function there, but it won't be a member function. It is the same as the following, which is more clear:
#include <complex>
#include <iostream>
class my_class {
public:
friend ostream& operator << (std::ostream& os, complex<double> a);
void output(complex<double>);
my_class() {}
~my_class() {}
};
std::ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
As it was already pointed out in the comments, the usage of friend is not necessary here.
Irrelevant to the question, but please be aware that resolving namespaces in a header file is generally a really-really bad idea, since all other files including it will implicitly resolve that namespace too. It can easily lead to vexing compilation errors in the long run.
I wouldn't call it a better way but a more clear way.
Here's your stream operator again:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
Its first parameter is the output stream. Since you do not have access to the output stream, you can't use the output stream operator as a member function unless you make it a friend of the class.
If you want to want to avoid using friend you can always define it as a function external to the class, and that is the most common way.
I'm trying to write a class that overloads the insertion operator but in my header file I get the error.
Overloaded 'operator<<' must be a binary operator (has 3 parameters)
Here is my code:
.h file
ostream & operator<<(ostream & os, Domino dom);
.cpp file
ostream & operator<< (ostream & os, Domino dom) {
return os << dom.toString();
}
I'm following a text book and this is what they use as an example but its not working for me.. Any suggestions?
You probably put your operator<< inside a class declaration. That means it takes an extra hidden parameter (the this parameter). You need to put it outside of any class declaration.
The insertion operator (<<) can be used as a member function or a friend function.
operator << used as a member function
ostream& operator<<(ostream& os);
This function should be invoked as :
dom << cout;
In general if you are using the operator as a member function, the left hand side of the operator should be an object. Then this object is implicitly passed as an argument to the member function. But the invocation confuses the user and it does not look nice.
operator << used as a friend function
friend ostream& operator<<(ostream& os, const Domino& obj);
This function should be invoked as :
cout << dom;
In this case the object dom is explicitly passed as a reference. This invocation is more traditional and user can easily understand the meaning of the code.
/*insertion and extraction overloading*/
#include<iostream>
using namespace std;
class complex
{
int real,imag;
public:
complex()
{
real=0;imag=0;
}
complex(int real,int imag)
{
this->real=real;
this->imag=imag;
}
void setreal(int real)
{
this->real=real;
}
int getreal()
{
return real;
}
void setimag(int imag)
{
this->imag=imag;
}
int getimag()
{
return imag;
}
void display()
{
cout<<real<<"+"<<imag<<"i"<<endl;
}
};//end of complex class
istream & operator >>(istream & in,complex &c)
{
int temp;
in>>temp;
c.setreal(temp);
in>>temp;
c.setimag(temp);
return in;
}
ostream &operator <<(ostream &out,complex &c)
{
out<<c.getreal()<<c.getimag()<<endl;
return out;
}
int main()
{
complex c1;
cin>>c1;
// c1.display();
cout<<c1;
//c1.display();
return 0;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Operator overloading
I didn't find any thing that could help me in this subject...
I'm trying to over load the << operator, this is my code:
ostream& Complex::operator<<(ostream& out,const Complex& b){
out<<"("<<b.x<<","<<b.y<<")";
return out;
}
this is the declaration in the H file:
ostream& operator<<(ostream& out,const Complex& b);
I get this error:
error: std::ostream& Complex::operator<<(std::ostream&, const Complex&) must take exactly one argument
what and why I'm doing wrong?
thanks
your operator << should be free function, not Complex class member in your case.
If you did your operator << class member, it actually should take one parameter, which should be stream. But then you won't be able to write like
std::cout << complex_number;
but
complex_number << std::cout;
which is equivalent to
complex_number. operator << (std::cout);
It is not common practice, as you can note, that is why operator << usually defined as free function.
class Complex
{
int a, b;
public:
Complex(int m, int d)
{
a = m; b = d;
}
friend ostream& operator<<(ostream& os, const Complex& complex);
};
ostream& operator<<(ostream& os, const Complex& complex)
{
os << complex.a << '+' << complex.b << 'i';
return os;
}
int main()
{
Complex complex(5, 6);
cout << complex;
}
More info here
As noted, the streaming overloads need to to be free functions, defined outside of your class.
Personally, I prefer to stay away from friendship and redirect to a public member function instead:
class Complex
{
public:
std::ostream& output(std::ostream& s) const;
};
std::ostream& operator<< (std::ostream& s, const Complex& c)
{
return c.output(s);
}
I've this program
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std ;
#if 0
namespace skg
{
template <class T>
struct Triplet ;
}
template <class T>
ostream& operator<< (ostream& os, const skg::Triplet<T>& p_t) ;
#endif
namespace skg
{
template <class T>
struct Triplet
{
// friend ostream& ::operator<< <> (ostream& os, const Triplet<T>& p_t) ;
private:
T x, y, z ;
public:
Triplet (const T& p_x, const T& p_y, const T& p_z)
: x(p_x), y(p_y), z(p_z) { }
} ;
}
template <class T>
ostream& operator<< (ostream& os, const skg::Triplet<T>& p_t)
{
os << '(' << p_t.x << ',' << p_t.y << ',' << p_t.z << ')' ;
return os ;
}
namespace {
void printVector()
{
typedef skg::Triplet<int> IntTriplet ;
vector< IntTriplet > vti ;
vti.push_back (IntTriplet (1, 2, 3)) ;
vti.push_back (IntTriplet (5, 5, 66)) ;
copy (vti.begin(), vti.end(), ostream_iterator<IntTriplet> (cout, "\n")) ;
}
}
int main (void)
{
printVector() ;
}
Compilation fails because compiler could not find any output operator for skg::Triplet. But output operator does exist.
If I move Triplet from skg namespace to global namespace everything works fine. what is wrong here ?
You need to move your implementation of operator<< into the same namespace as your class. It's looking for:
ostream& operator<< (ostream& os, const skg::Triplet<T>& p_t)
But won't find it because of a short-coming in argument-dependent look-up (ADL). ADL means that when you call a free function, it'll look for that function in the namespaces of it's arguments. This is the same reason we can do:
std::cout << "Hello" << std::endl;
Even though operator<<(std::ostream&, const char*) is in the std namespace. For your call, those namespaces are std and skg.
It's going to look in both, not find one in skg (since yours is in the global scope), then look in std. It will see possibilities (all the normal operator<<'s), but none of those match. Because the code running (the code in ostream_iterator) is in the namespace std, access to the global namespace is completely gone.
By placing your operator in the same namespace, ADL works. This is discussed in an article by Herb Sutter: "A Modest Proposal: Fixing ADL.". (PDF). In fact, here's a snippet from the article (demonstrating a shortcoming):
// Example 2.4
//
// In some library header:
//
namespace N { class C {}; }
int operator+( int i, N::C ) { return i+1; }
// A mainline to exercise it:
//
#include <numeric>
int main() {
N::C a[10];
std::accumulate( a, a+10, 0 ); // legal? not specified by the standard
}
Same situation you have.
The book "C++ Coding Standards" by Sutter and & Alexandrescu has a useful guideline:
Keep a type and its nonmember function interface in the same namespace.
Follow it and you and ADL will be happy. I recommend this book, and even if you can't get one at least read the PDF I linked above; it contains the relevant information you should need.
Note that after you move the operator, you'll need your friend directive (so you can access private variables):
template <typename U>
friend ostream& operator<< (ostream& os, const Triplet<U>& p_t);
And ta-da! Fixed.