How to implement the extraction operator in a class? - c++

I have a class that reads parts of a binary file into variables of different types.
class Foo {
public:
size_t getSizeT();
float getFloat();
std::string getString();
private:
std::ifstream stream;
};
Now I'd like to implement the stream extraction operator as described in this answer.
class Foo {
public:
Foo &operator>>(Foo &foo, size_t &value);
Foo &operator>>(Foo &foo, float &value);
Foo &operator>>(Foo &foo, std::string &value);
private:
std::ifstream stream;
};
The code fails to compile with this error message: error C2804: binary 'operator >>' has too many parameters. How to properly override the stream extraction operator? It should distinguish between types and be chainable.

As free function, operator signature should be:
Foo& operator >>(Foo& foo, size_t& value);
As member function (your case), it should be:
Foo& operator >>(size_t& value);

If an instance of your class is the source of the data, then you have two ways of writing the input operator function: Either as a stand-alone global function taking two arguments, the instance of your class and the destination object. Or you write it as a member-function of your class, and then it takes only a single argument which is the destination.
So for a global function you write e.g.
class Foo { ... };
Foo& operator>>(Foo& foo, int& i)
{
// Get an integer and writes to `i` here
return foo;
}
For a member function you write e.g.
class Foo
{
public:
...
Foo& operator>>(int& i)
{
// Get an integer and writes to `i` here
return *this;
}
};
The reason I think you wrote the operator wrong, is because you can write the first version, using global functions, as friend function inline inside a class, and you have seen that before mistaking between the difference between a friend function and a member function.
You use friend functions like
class Foo
{
public:
...
// Notice the keyword `friend`
friend Foo& operator>>(Foo& foo, int& i)
{
// Get an integer and writes to `i` here
return foo;
}
};
The difference between a member function and a friend function is subtle but very important.

Related

function call operator in class or method?

class foo
{
public:
struct bar
{
bar() {}
int bar_var;
};
operator std::vector<bar>() {
return m_list;
}
private:
std::vector<bar> m_list;
int foo_var;
};
Here defined a class foo, what is the semantic "operator std:vector<bar>()" mean here? I don't think it is an overloaded function call operator.
Compile with the above code works OK
what is the semantic "operator std:vector()" mean here?
It denotes a conversion operator that allows you to use a foo object where a std::vector<bar> is expected. A conversion operator is a special kind of member function that converts a value of a class type to a value of some other type.
For example, say we have a function called func that takes a std::vector<foo::bar> as its only parameter. Now,
you can even call this function by passing a foo object instead of passing a std::vector<foo::bar> as shown below:
//--------vvvvvvvvvvvvvvvvvvvvv----------> expects std::vector<foo::bar>
void func(std::vector<foo::bar> m)
{
std::cout<<"func called"<<std::endl;
}
int main()
{
foo fObject;
//-------vvvvvvv---->passing a foo object which implicitly uses the conversion operator
func(fObject);
}
Working demo
In the above demo, func expects a std::vector<foo::bar>. But we're passing fObject which is an object of type foo and so there will be an implicit conversion of fObject to std::vector<foo::bar> using the conversion operator that you provided.
It's a conversion function. In your example, a foo will happily call that function if it's ever used in a context where a std::vector<bar> is expected. A more typical use case might look something like
class MyCustomNumberType {
private:
// Super secret number arithmetic stuff.
public:
operator double() {
// Convert to a double and return here...
}
}
MyCustomNumberType foo = /* more complicated math ... */;
double bar = foo + 1.0;

Overloading the stream insertion (<<) operator for a class

It is often overloaded as a friend function of the class. Is there any way it can be overloaded as a member function?
Is there any way it can be overloaded as a member function?
Let's say if you have a class Foo and you want to use:
Foo foo;
std::cout << foo;
No, it cannot.
A member function overload works only if the first argument is an object of the class. In the case of stream insertion operators, the first argument is a stream, not an object of the class.
If you want to use:
Foo foo;
foo << std::cout;
Yes, it can be defined as a member function.
A non-member function and a virtual member function can be combined to good effect when used in a situation where derived classes are involved.
struct Shape
{
// Member function that can be overridden by derived classes.
virtual std::ostream& operator<<(std::ostream& os) const = 0;
};
// Non-member function that makes use of member functions.
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape << os;
}
struct Rectangle : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream a Rectangle.
// ...
return os;
}
};
struct Ellipse : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream an Ellipse.
// ...
return os;
}
};
Usage:
Rectangle r;
Ellipse e;
std::cout << r << std::endl;
std::cout << e << std::endl;
If you wanted to badly enough, you could use a member function overload, but it's directly contrary to convention, so doing it would lead to confusion. It would also prevent chaining extraction/insertion operators, and wouldn't work for reading/writing primitive types.
The reason behind this is that invoking an operator overloaded as a member function means that x << y; is interpreted as x.operator<<(y);, so the overloaded operator has to be a member of the left operand, not the right. It's possible to do that (iostreams include such overloads for some types), but it's essentially impossible to extend (all such overloads have to be part of the iostream object when it's the left operand).
If you want to overload it as a member of the object to be read/written, you need to put the object being read/written as the left operand. This means insertion would go from left to right instead of right to left. To have at least some chance of maintaining sanity, you'd almost certainly want to use >> for insertion, and << for extraction:
class my_class {
int x;
public:
bool operator<<(std::istream &is) {
// Note the reversal here. That's because we're defining this
// for a `my_class` on the left, and an iostream on the right,
// but the existing `>>` and `<<` use the reverse of that (iostream
// on the left).
is >> x;
return is.good();
}
bool operator>>(std::ostream &os) {
os << x;
return os.good();
}
};
my_class a;
a >> std::cout;
a << std::cin;
Note: I'm providing this answer only to point out that it's technically possible to do this, and show how. If you were starting over with a clean slate and you were really set on using member functions, I can see where you might conceivably choose this method--but even then, it's open to a lot of question.
In particular (as noted above) this would not support chaining. Since the insertion and extraction are done as member functions of the left operand, it also means it would only work for user-defined types, not any primitive types (int, short, long, float, double, bool, etc.)
Bottom line: if you want to badly enough, you can get it to work to a limited degree under limited circumstances--but neither well (no chaining) nor universally (no primitive types).
Is there any way it can be overloaded as a member function?
No. The signature of the function prevents this option.
// Binary operator where the stream object is left of '<<' and the object
// instance is right of '<<'
std::ostream& operator<<(std::ostream& lhs, const Foo& rhs)
For illustration here's a binary operator+ as a free function:
class Foo
{
};
Foo operator+(const Foo& lhs, const Foo& rhs)
{
// an appropriate implementation
}
int main()
{
Foo f1;
Foo f2;
// Uses the free function
Foo result = f1 + f2;
return 0;
}
However implemented as a member function it looks like this:
class Foo
{
public:
Foo operator+(const Foo& other) const
{
// an appropriate implementation
}
};
int main()
{
Foo f1;
Foo f2;
// The calling sequence is the same as before however 'f1' is logically
// the same as 'lhs' in the free function implementation example (i.e.,
// the first type in the binary operator must be the class type when
// implemented as a member function)
Foo result = f1 + f2;
return 0;
}
Given the operator+ member function example it is easier to see why the std::ostream& operator<<(std::ostream& lhs, const Foo& rhs) free function cannot be converted to an equivalent member function. Because 'lhs' would need to be the same type as std::ostream but this is only possible when implementing that class whereas in this example the Foo class is being implemented.

how does this typedef syntax works..?

#include<iostream.h>
#include<conio.h>
typedef ostream& (*T)(ostream& , int);
class Base
{
T fun;
int var;
public:
Base(T func, int arg): fun(func) , var(arg)
{};
friend ostream& operator<<(ostream& o, Base& obj)
{
return obj.fun(o,obj.var);
}
};
ostream& odisp(ostream& o, int i);
{
o<<”i=”<<i<<endl;
return o;
}
Base disp(int i)
{
return base(odisp, i)
};
I am totally stuck since the first line since i cant figure out how this typedef works.. it looks like a pointer to function syntax but again ostream has me puzzled..?? pls do explain how this whole code works..??
#include <iostream.h>
#include <conio.h>
As it has been pointed out, iostream.h and conio.h are not standard headers for C++ programs. The correct header include statement for the IO streams library is #include <iostream>, without the extension.
typedef ostream& (*T)(ostream& , int);
This creates a typedef named T which is a pointer to a function with these properties:
returns a reference to ostream
accepts two parameters, in this order:
a reference to an ostream
int value
ostream, assuming it's referring to std::ostream, is itself a typedef of std::basic_ostream, which is found in the C++ standard library. It is defined as:
namespace std {
typedef basic_ostream<char> ostream;
}
Objects std::cout are instances of std::ostream.
class Base
{
T fun; // (1)
int var; // (2)
public:
Base(T func, int arg): fun(func) , var(arg) {}; // (3)
friend ostream& operator<<(ostream& o, Base& obj) // (4)
{
return obj.fun(o, obj.var);
}
};
This is a class that holds two things: (1) a pointer to a function as described above and (2) an integer. The constructor (3) allows users of the class to instantiate it with a function pointer and an integer.
The friend function declaration (4) overloads the left bitshift operator <<. This sort of overloading is called operator overloading. By convention, The operator << is also called the stream insertion operator in the context of IO streams.
Note that friend functions defined this way are actually not members of Base, and thus do not receive a this pointer (hence, the need for a separate Base& parameter).
ostream& odisp(ostream& o, int i);
{
o << "i=" << i << endl;
return o;
}
This is a function called odisp. It takes in a reference to an ostream and an integer. If you pass in the integer 42, it prints out the passed-in integer in this form:
i=42
Base disp(int i)
{
return base(odisp, i)
};
This function has multiple syntax errors and will not run as-is:
base is probably meant to be Base. In this case it would construct a Base temporary and returns it.
Missing a semicolon.
These issues are somewhat fundamental to the language. You may want to pick up a good introductory C++ book which will cover these issues.

C++ adding friend to a template class in order to typecast

I'm currently reading "Effective C++" and there is a chapter that contains code similiar to this:
template <typename T>
class Num {
public:
Num(int n) { ... }
};
template <typename T>
Num<T> operator*(const Num<T>& lhs, const Num<T>& rhs) { ... }
Num<int> n = 5 * Num<int>(10);
The book says that this won't work (and indeed it doesn't) because you can't expect the compiler to use implicit typecasting to specialize a template.
As a soluting it is suggested to use the "friend" syntax to define the function inside the class.
//It works
template <typename T>
class Num {
public:
Num(int n) { ... }
friend
Num operator*(const Num& lhs, const Num& rhs) { ... }
};
Num<int> n = 5 * Num<int>(10);
And the book suggests to use this friend-declaration thing whenever I need implicit conversion to a template class type. And it all seems to make sense.
But why can't I get the same example working with a common function, not an operator?
template <typename T>
class Num {
public:
Num(int n) { ... }
friend
void doFoo(const Num& lhs) { ... }
};
doFoo(5);
This time the compiler complaints that he can't find any 'doFoo' at all.
And if i declare the doFoo outside the class, i get the reasonable mismatched types error. Seems like the "friend ..." part is just being ignored.
So is there a problem with my understanding? What is the difference between a function and an operator in this case?
The reason is that here
doFoo(5);
the compiler has no way of finding foo, given an int parameter. This would be the equivalent of calling your friend operator like this:
Num<int> n = 5 * 10;
This will "work", but not by calling the friend operator* defined in your Num class, but by calling the built-in operator* for integers, and then using the implicit conversion from Num's converting constructor.
The core problem is lookup. A friend declaration provides a declaration of a namespace level function, but the declaration is only available inside the class that is befriending it. In the example the book provides that is not an issue: the function takes two arguments of the enclosing type, as long as one of them is of the enclosing type, Argument Dependent Lookup will look inside the definition of the class and find the operator. In your case that is not the case, since there is a single argument and that needs a conversion, the compiler will not look inside the definition of the class.
Note that this is regardless of templates and conversions:
class A {
friend void f( int ) {}
friend void g( int, A ) {}
};
int main() {
f(5); // Error: lookup cannot find 'f' declared *only* inside A
g(5,A()); // Ok, one argument is 'A', lookup will find the function
}
In the case above, where there are no templates involved, you could potentially add a declaration at namespace level to fix it, but that is not really an option for template classes.
class A {
friend void f() { std::cout << "inside A\n"; }
};
void f(int); // only declaration
int main() {
f(5); // "inside A"
}
This cannot be done for a template (and for all instantiating types) as the friend declaration is a declaration of a non-templated function. Although you could can play with the code just for the sake of testing:
template <typename T>
struct Num {
Num(int x) ...
friend void f( Num const & );
};
Num<int> f(Num<int> const &); // only declaration
int main() {
f(5);
}
Yes these code compiler do not know how to work with it .
like
doFoo(5)
compiler do not know 5 is int

C++ - Using a template to return a const reference publicly and a non const reference privately

The question: How can I make it so that a const reference is returned publicly and a non const reference returned privately?
I'm trying to create a read-only template for some variables in my classes. This involves a template class which returns a const reference to the data when public. However in the class I need to operate on the data so I am trying to return a reference that is not const privately. Here's the basics:
private: operator T&() { return data; }
public: operator const T&() const { return data; }
When I add the non const reference as shown above, if I try to access the variable publicly my Visual Studio 2010 cl.exe compiler tells me it cannot access the private member in the class. Something as simple as cout << myobj.x << endl if x was declared using the template will fail.
error C2248: 'proxy<T,C>::operator int &' : cannot access private member declared in class 'proxy<T,C>'
Here is the other thread for reference:
C++ - How to make read only class member variables in Visual Studio 2010 - Stack Overflow
Edit:
You asked for the code so here it is.
template <class T, class C>
class proxy {
friend C;
private:
T data;
T operator=(const T& arg) { data = arg; return data; }
operator T&() { return data; } // I'd expect this is only returned privately
public:
operator const T&() const { return data; }
};
class myClass {
public:
proxy<int,myClass> x;
void f(int i) {
x = i;
}
};
int main(int argc, char **argv)
{
myClass test;
test.f(12);
cout << test.x << endl; // Compiler error trying to access non-const T&
return 0;
}
Actually, visibility and accesibility are independent things in C++:
Visibility rules say that all the member functions are considered when resolving an overload.
Accesibility means that if the chosen overload function is not accesible from the used context (private member from outside of the class, for example) a compiler error will happen.
Some people think that private members will not participate in overload resolution if the function in called from outside of the class, but that's not the case. All functions, irrespective of the access, are considered.
About your specific problem, you do:
std::cout << test.x;
Here test is non-const, so is test.x, and of the two overload conversion functions, the non-const one is chosen. But, alas, this function is private, thus compiler error.
The quick solution is to do a const_cast:
std::cout << const_cast<const myClass&>(test).x;
Or if you prefer:
const myClass &ctest = test;
std::cout << ctest.x;
The right solution would be to just remove the non-const private one. You don't need it, since from the class context you can use the data member directly.
Frankly, it looks like you are trying to implement properties in C++ using the syntax from other languages. Properties are fine, but that's not the C++ way.
My advice is: do not fight the language, accept the syntax as it is, and just do the parenthesis thing. Or if x does not hold an invariant, just do it public.
The shortest way would be something like:
class myClass {
private:
int _x;
public:
int x() const {
return _x;
}
//if needed
void x(int value) {
_x = value;
}
};
The people that will read your code in the future (mind you, it might be me!) will greatly appreciate that you do not try and reinvent the language.
In C++, access checks are done after overload resolution. This has both advantages and disadvantages over the other possibility -- removing inaccessible functions from the candidate set.
Usually the solution is to use a different name for the private function. But it appears that you're trying to conform to a particular interface required by some functions you've befriended. I don't think there's an easy workaround for that. Private inheritance won't help in the general case, because inherited functions aren't part of the candidate set, they're hidden by a function in the derived class. But conversion functions are inherited... and after testing, it seems that the original problem recurs (even a private conversion in a private base class is found).
So I finally suggest using a named function instead of a conversion, as in:
template <typename T, typename C>
class proxy
{
friend C;
private:
T data;
T operator=(const T& arg) { data = arg; return data; }
T& mutate() { return data; }
public:
operator const T&() const { return data; }
};
class myClass
{
public:
proxy<int,myClass> x;
void f(int i)
{
x.mutate() = i;
}
};
test is not const, test.x is not const, so myClass::operator int() is a better match that myClass::operator int() const.
Access control (private/public) doesn't enter into it.