Can inserter/extractor operator overrides be made run-time polymorphic?

R

Randy

Since these operators can't be member functions, and since
friend functions can't be declared virtual, how do I make my
inserters and extractors polymorphic?

--Randy Yates
 
V

Victor Bazarov

Randy said:
Since these operators can't be member functions, and since
friend functions can't be declared virtual, how do I make my
inserters and extractors polymorphic?

Make another member virtual and call it in your operator <<.

struct Base {
virtual ostream& output(ostream&) const = 0;
};

ostream& operator << (ostream& os, Base const& b) {
return b.output(os);
}

struct Derived : Base { ...

V
 
R

Roland Pibinger

Since these operators can't be member functions, and since
friend functions can't be declared virtual, how do I make my
inserters and extractors polymorphic?

by operator overloading, eg.

ostream& operator<< (ostream& out, const Base& base);
ostream& operator<< (ostream& out, const Derived& derived);
....

Best wishes,
Roland Pibinger
 
R

Randy

Really? So if I did that and I had

class Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);
}

and

class Derived : public Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);
}

and then

int main(int argc, char* argv[])
{
Base* b;
b = new Derived;
cout << b;
return 0;
}

the Derived inserter would be used and not the Base inserter?

Thanks Roland.

--Randy
 
R

Roland Pibinger

Really? So if I did that and I had

class Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);
}

and

class Derived : public Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);

friend ostream& operator<< (ostream& os, const Derived& derived);
}

and then

int main(int argc, char* argv[])
{
Base* b;
b = new Derived;

No need to 'new' anything. C++ objects can exist on the stack.
cout << b;
return 0;
}

the Derived inserter would be used and not the Base inserter?

It's just function overloading (like in Java or C#).

Best wishes,
Roland Pibinger
 
R

Randy Yates

friend ostream& operator<< (ostream& os, const Derived& derived);

Right.
}

and then

int main(int argc, char* argv[])
{
Base* b;
b = new Derived;

No need to 'new' anything. C++ objects can exist on the stack.
cout << b;
return 0;
}

the Derived inserter would be used and not the Base inserter?

It's just function overloading (like in Java or C#).

I'm confused - how can it "just be function overloading?"
This is a run-time selection, not compile-time, right?

I thought the usual usage of the term "function overloading"
was reserved for compile-time overloading, while "polymorphism"
was used for run-time overloading. Am I mistaken?
--
% Randy Yates % "Watching all the days go by...
%% Fuquay-Varina, NC % Who are you and who am I?"
%%% 919-577-9882 % 'Mission (A World Record)',
%%%% <[email protected]> % *A New World Record*, ELO
http://home.earthlink.net/~yatescr
 
R

Randy Yates

[...]
int main(int argc, char* argv[])
{
Base* b;
b = new Derived;

No need to 'new' anything. C++ objects can exist on the stack.

True, but my point was to question run-time polymorphism, not
compile-time polymorphism.
--
% Randy Yates % "My Shangri-la has gone away, fading like
%% Fuquay-Varina, NC % the Beatles on 'Hey Jude'"
%%% 919-577-9882 %
%%%% <[email protected]> % 'Shangri-La', *A New World Record*, ELO
http://home.earthlink.net/~yatescr
 
J

Jim Langston

Randy Yates said:
Really? So if I did that and I had

class Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);
}

and

class Derived : public Base
{
...
friend ostream& operator<< (ostream& os, const Base& base);

friend ostream& operator<< (ostream& os, const Derived& derived);
Right.
}

and then

int main(int argc, char* argv[])
{
Base* b;
b = new Derived;

No need to 'new' anything. C++ objects can exist on the stack.
cout << b;
return 0;
}

the Derived inserter would be used and not the Base inserter?

It's just function overloading (like in Java or C#).

I'm confused - how can it "just be function overloading?"
This is a run-time selection, not compile-time, right?

I thought the usual usage of the term "function overloading"
was reserved for compile-time overloading, while "polymorphism"
was used for run-time overloading. Am I mistaken?

There is run time and compile time polymorphism AFAIK.
 
R

Roland Pibinger

There is run time and compile time polymorphism AFAIK.

The function call is resolved at compile time. I guess Victor Bazarov
has the right answer how to make inserter/extractor "run-time
polymorphic". Sorry for causing confusion.

Best wishes,
Roland Pibinger
 
R

Randy Yates

The function call is resolved at compile time. I guess Victor Bazarov
has the right answer how to make inserter/extractor "run-time
polymorphic". Sorry for causing confusion.

Acknowledged. Thanks for the correction.
--
% Randy Yates % "So now it's getting late,
%% Fuquay-Varina, NC % and those who hesitate
%%% 919-577-9882 % got no one..."
%%%% <[email protected]> % 'Waterfall', *Face The Music*, ELO
http://home.earthlink.net/~yatescr
 
R

Randy

Victor et al.,

Why are you using the "const" qualifier in

ostream& operator << (ostream& os, Base const& b) {

? And also, is the placement of the reference operator "&"
after "const" required or can it also be after Base, e.g.,

ostream& operator << (ostream& os, Base& const b) {

Let me guess: The first way tells the object pointed to
is constant, the second tells the pointer is constant. ??

--Randy
 
B

Ben Pope

Randy said:
Victor et al.,

Why are you using the "const" qualifier in

ostream& operator << (ostream& os, Base const& b) {

Same as always... b is not modified.
? And also, is the placement of the reference operator "&"
after "const" required or can it also be after Base, e.g.,

ostream& operator << (ostream& os, Base& const b) {

Let me guess: The first way tells the object pointed to
is constant, the second tells the pointer is constant. ??

Since there is no pointer, that is not possible. A reference is
initialised to refer to one object and cannot be changed.

Read the type from right to left:

int main()
{
Base base;
Base& const a = base; // a is a const reference to a Base,
'&' is // Ignored - all references are const
Base const& b = base; // b is a reference to a const Base
const Base& c = base; // c is a reference to a const Base;

Base* base_p;
Base const * const ap = base_p; // ap is a const ptr to a const Base
const Base * const bp = base_p; // bp is a const ptr to a const Base
Base * cp = base_p; // cp is a pointer to Base
Base * const dp = base_p; // dp is a const ptr to a Base
}



Ben Pope
 
V

Victor Bazarov

Randy said:
Victor et al.,

Why are you using the "const" qualifier in

ostream& operator << (ostream& os, Base const& b) {

?

The output is supposedly not changing the object. If it is so, why not
explicitly state that by declaring the object 'const'?

Also, having a 'const' here allows you to output a temporary.
> And also, is the placement of the reference operator "&"

It's not really a "reference operator". It's just part of the declaration
syntax.
after "const" required or can it also be after Base, e.g.,

ostream& operator << (ostream& os, Base& const b) {

Learn the declarations. The declaration

Base & const b

(if allowed) would mean that 'b' is a _constant_ reference to non-constant
Base object. Since references are not objects, they cannot be
cv-qualified (made 'const' or 'volatile'). Hence it's not allowed.
Let me guess: The first way tells the object pointed to
is constant, the second tells the pointer is constant. ??

There are no pointers here.

V
 
R

Randy

There are no pointers here.

Bullshit. What do you think a reference is? It is a pointer
in which the compiler automatically handles
dereferencing. From Schildt's "Teach Yourself C++"
2e, in reference to the function "void f(int &n)",

...each time n is used within f(), it is automatically
treated as a POINTER to the argument used to
call f().

I'm sure that is exactly what a implementation does
with references. Anything else (e.g., copying to a
temporary and then recopying when done) would be
insanely inefficient and pointless.

Pointer isn't a dirty word - don't be afraid to use it.

--Randy Yates
 
V

Victor Bazarov

Randy said:
Bullshit.

No. There were no pointers there.
> What do you think a reference is? It is a pointer

No, it is a reference.
in which the compiler automatically handles
dereferencing. From Schildt's "Teach Yourself C++"

If you manage to derive any worthwhile knowledge from Schildt's books,
you're a genius. Most likely, you're just using wrong source of
information and get confused. If you want to be viewed seriously here,
do not quote from Schildt's books.
2e, in reference to the function "void f(int &n)",

...each time n is used within f(), it is automatically
treated as a POINTER to the argument used to
call f().

I'm sure that is exactly what a implementation does

I am not. Nowhere in the Standard can we read that a reference is
"a pointer that is automatically dereferenced" (or some such). And the
Standard is _infinitely_ more trusted source of information that Schildt's
books.
with references. Anything else (e.g., copying to a
temporary and then recopying when done) would be
insanely inefficient and pointless.

Who said anything about copying? Why can't a reference be implemented in
some other way, like an index or other indirection? If you can't think of
any other way of implementation than pointers, it doesn't mean there can
be none. FWIW, the function can be inlined, and then there are no real
arguments -- everything is as if the body of the function is inserted into
the calling scope and the formal arguments are replaced with the factual
ones.
Pointer isn't a dirty word - don't be afraid to use it.

I am not. No matter what you managed to pollute your brain with by
reading Schildt's books, there were no pointers there. Those were
references, references are not objects, and as such cannot be qualified
as const. Write it on the board 100 times, then report back to us.

V
 
B

Ben Pope

Randy said:
Bullshit. What do you think a reference is? It is a pointer
in which the compiler automatically handles
dereferencing.

It doesn't have to be. It could be implemented in a completely
different way. The standard mandates no such thing.
> From Schildt's "Teach Yourself C++"
2e, in reference to the function "void f(int &n)",

...each time n is used within f(), it is automatically
treated as a POINTER to the argument used to
call f().

Nope. There is no requirement to implement a reference as a pointer
with syntactic sugar.
I'm sure that is exactly what a implementation does
with references.

Why are you so sure?
> Anything else (e.g., copying to a
temporary and then recopying when done) would be
insanely inefficient and pointless.

Perhaps it done with magic? Why should you care?
Pointer isn't a dirty word - don't be afraid to use it.

Neither is "reference".

Ben Pope
 
T

TB

Randy sade:
Bullshit. What do you think a reference is? It is a pointer
in which the compiler automatically handles
dereferencing. From Schildt's "Teach Yourself C++"
2e, in reference to the function "void f(int &n)",

...each time n is used within f(), it is automatically
treated as a POINTER to the argument used to
call f().

I'm sure that is exactly what a implementation does
with references. Anything else (e.g., copying to a
temporary and then recopying when done) would be
insanely inefficient and pointless.

Pointer isn't a dirty word - don't be afraid to use it.

--Randy Yates

You might be confused. References might be handled with similarities
to pointers by the compiler and hardware, but the C++ Standard
provides references as a concept on its own, and should be
acknowledged as such by programmers.

Snipped from The C++ Standard 8.3.2/1
"a reference can be thought of as a name of an object."

How references are treated during execution of compiled code
is of no concern. A machine could just as well contain a name cache
holding aliases for objects in memory without dealing with address pointers.

TB
 
R

Randy

I reserve the right to investigate and understand "what's under the
hood" of any code-generating tool I use. If that is a problem for
the tool maker, I'll start looking for another tool, because
the day this becomes unknowable is the day we start
losing touch with reality. The implementation matters,
the hardware matters, the assembly code generated
matters.

It sounds to me like you all know damn well that a reference
is a pointer with some help from the compiler, but would
prefer to dance around the fact. If you really think it's
not, then find a compiler writer around here who can
explain how they actually implemented it.

--RY
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top