473,416 Members | 1,888 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

wrong compiler warning?

Hi all,

I've a problem. The code that follows creates a warning in both gcc and
visual c++. However, I think it's correct: basically, there is a
function that return an object of a derived class, that's bounded to a
base class reference to delay the destruction of the actual object to
the end of the reference scope. Actually, I don't use the reference: the
code that matters is in the destructor, and I want it to be executed at
the end of the method.

Really strange, both the compilers warn me about the "useless"
reference... I'm feared that if the compilers "think" that the reference
is useless, they could try some dangerous optimization...

Here follows a simple example:
#include <iostream>

class Base
{
public:
Base() { std::cout << "Base\n"; std::cout.flush(); }
virtual ~Base() { std::cout << "~Base\n"; std::cout.flush(); }

virtual char* Name() const { return "Base"; }
};

class Derived : public Base
{
public:
Derived() { std::cout << "Derived\n"; std::cout.flush(); }
~Derived() { std::cout << "~Derived\n"; std::cout.flush(); }

char* Name() const { return "Derived"; }
};

Derived foo()
{
std::cout << "foo function\n"; std::cout.flush();
return Derived();
}

int main()
{
std::cout << "begin of the program\n"; std::cout.flush();
const Base& obj = foo();
std::cout << "this is the program body\n"; std::cout.flush();

return 0;
}


Thank you,

Zeppe
Sep 11 '06 #1
11 1992
zeppe wrote:
I've a problem. The code that follows creates a warning in both gcc
and visual c++. However, I think it's correct: basically, there is a
function that return an object of a derived class, that's bounded to a
base class reference to delay the destruction of the actual object to
the end of the reference scope. Actually, I don't use the reference:
the code that matters is in the destructor, and I want it to be
executed at the end of the method.
Just declare an object instead of a reference.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 11 '06 #2
Victor Bazarov wrote:
zeppe wrote:
>I've a problem. The code that follows creates a warning in both gcc
and visual c++. However, I think it's correct: basically, there is a
function that return an object of a derived class, that's bounded to a
base class reference to delay the destruction of the actual object to
the end of the reference scope. Actually, I don't use the reference:
the code that matters is in the destructor, and I want it to be
executed at the end of the method.

Just declare an object instead of a reference.

V
if i declare an object instead of a reference i lose the type polymorphism.

i.e., output with reference:

begin of the program
foo function
Base
Derived
this is the program body
~Derived
~Base
output with object:

begin of the program
foo function
Base
Derived
~Derived
~Base
this is the program body
~Base
Of course in the real world i don't know that foo returns Derived, so
the object should be Base.

Zeppe
Sep 11 '06 #3
zeppe wrote:
Victor Bazarov wrote:
>zeppe wrote:
>>I've a problem. The code that follows creates a warning in both gcc
and visual c++. However, I think it's correct: basically, there is a
function that return an object of a derived class, that's bounded
to a base class reference to delay the destruction of the actual
object to the end of the reference scope. Actually, I don't use the
reference: the code that matters is in the destructor, and I want
it to be executed at the end of the method.

Just declare an object instead of a reference.

V

if i declare an object instead of a reference i lose the type
polymorphism.
What polymorphism? Polymorphism in deleting it? D-tors cannot call
virtual functions polymorphically. If you want to rely on proper
d-tor to be called, you probably need to use 'auto_ptr' and return
a pointer from your function, not a temporary.
i.e., output with reference:

[..]

Of course in the real world i don't know that foo returns Derived, so
the object should be Base.
Huh?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 11 '06 #4
Victor Bazarov wrote:
>if i declare an object instead of a reference i lose the type
polymorphism.

What polymorphism? Polymorphism in deleting it? D-tors cannot call
virtual functions polymorphically. If you want to rely on proper
d-tor to be called, you probably need to use 'auto_ptr' and return
a pointer from your function, not a temporary.
I don't see the difference. If I have

class Derived: public Base

and i return a temporary Derived, and I attach a reference const Base&,
I have polymrphism in descructor, that is, i delay the Temporary
destruction until the end of the reference lifetime.
>>
Of course in the real world i don't know that foo returns Derived, so
the object should be Base.

Huh?
I have

Derived foo();

I can solve writing:

Derived obj = foo();

but if I have a more complex sitation and i don't know that foo returns
a Derived, i can only rely in auto_ptr or in references.

Bye,

Zeppe
Sep 11 '06 #5
zeppe wrote:
[..]
I have

Derived foo();

I can solve writing:

Derived obj = foo();

but if I have a more complex sitation and i don't know that foo
returns a Derived, i can only rely in auto_ptr or in references.
Your 'foo' returns _an_object_. How can you not know what it is?
Your 'foo' doesn't return a reference, in which case you could claim
the ability to use polymorphism. If it's slicing you're trying to
avoid, your 'foo' has already sliced everything, binding a reference
to it is pointless.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 11 '06 #6
Victor Bazarov ha scritto:
Your 'foo' returns _an_object_. How can you not know what it is?
Your 'foo' doesn't return a reference, in which case you could claim
the ability to use polymorphism.
You are right. But actually, in a more complex example, the real object
could be somewhat hidden, for example with traits. Consider the
following example (a bit longer):

#include <iostream>

class Base
{
public:
Base() { std::cout << "Base\n"; std::cout.flush(); }
virtual ~Base() { std::cout << "~Base\n"; std::cout.flush(); }

virtual char* Name() const { return "Base"; }
};

class Derived : public Base
{
public:
Derived() { std::cout << "Derived\n"; std::cout.flush(); }
~Derived() { std::cout << "~Derived\n"; std::cout.flush(); }

char* Name() const { return "Derived"; }
};

template <class T>
struct Bar_traits
{
typedef Base ret_type;
};
template <>
struct Bar_traits<int>
{
typedef Derived ret_type;
};

template <class T>
typename Bar_traits<T>::ret_type foo(){
std::cout << "foo function\n"; std::cout.flush();
return typename Bar_traits<T>::ret_type();
}
int main()
{
std::cout << "begin of the program\n"; std::cout.flush();
const Base& obj = foo<int>();
std::cout << "this is the program body\n"; std::cout.flush();

return 0;
}

I know I could declare a traits, i.e. Bar_traits<intobj = foo<int>();
but is not always clean to do so. I was asking if binding the return
temporary type polimorphically on a reference is allowed.
If it's slicing you're trying to
avoid, your 'foo' has already sliced everything, binding a reference
to it is pointless.
Why has sliced? I returned a 'Derived', that's all. Binding a 'Derived'
with a 'Base' reference it's illegal (I don't think)? It produces slicing?

Thank you for answers.

Zeppe
Sep 12 '06 #7
zeppe wrote:
Victor Bazarov ha scritto:
>Your 'foo' returns _an_object_. How can you not know what it is?
Your 'foo' doesn't return a reference, in which case you could claim
the ability to use polymorphism.

You are right. But actually, in a more complex example, the real
object could be somewhat hidden, for example with traits. Consider the
following example (a bit longer):

#include <iostream>

class Base
{
public:
Base() { std::cout << "Base\n"; std::cout.flush(); }
virtual ~Base() { std::cout << "~Base\n"; std::cout.flush(); }

virtual char* Name() const { return "Base"; }
};

class Derived : public Base
{
public:
Derived() { std::cout << "Derived\n"; std::cout.flush(); }
~Derived() { std::cout << "~Derived\n"; std::cout.flush(); }

char* Name() const { return "Derived"; }
};

template <class T>
struct Bar_traits
{
typedef Base ret_type;
};
template <>
struct Bar_traits<int>
{
typedef Derived ret_type;
};

template <class T>
typename Bar_traits<T>::ret_type foo(){
std::cout << "foo function\n"; std::cout.flush();
return typename Bar_traits<T>::ret_type();
}
int main()
{
std::cout << "begin of the program\n"; std::cout.flush();
const Base& obj = foo<int>();
std::cout << "this is the program body\n"; std::cout.flush();

return 0;
}

I know I could declare a traits, i.e. Bar_traits<intobj =
foo<int>(); but is not always clean to do so.
Not always? What are you talking about?

All you need to do is to use the function itself to introduce the
type. With introduction of TR1 it's going to be very easy, AFAIUI:

std::tr1::result_of<foo<int obj = foo<int>();

Meanwhile you can probably use 'Boost'.
I was asking if binding
the return temporary type polimorphically on a reference is allowed.
Yes, it's allowed. That's why you have a *warning* and not an *error*
in your program. Simply ignore your warning if you don't want to make
changes to have your program compile cleanly.
>If it's slicing you're trying to
avoid, your 'foo' has already sliced everything, binding a reference
to it is pointless.

Why has sliced? I returned a 'Derived', that's all. Binding a
'Derived' with a 'Base' reference it's illegal (I don't think)? It
produces slicing?
No. Binding a reference does not introduce slicing. Read what I wrote
more carefully, and think about it before replying.

Now, think about it. Next time somebody makes your 'foo<int>' return
a type that is not a descendant of 'Base'. What do you do then? That
is why you shouldn't stop mid-stream when making your stuff generic.
If your function relies on some traits template to return a proper
object type, use the same traits to declare the receiving object.

Is there anything else here that needs clarification?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 12 '06 #8
Victor Bazarov ha scritto:
>I know I could declare a traits, i.e. Bar_traits<intobj =
foo<int>(); but is not always clean to do so.

Not always? What are you talking about?
Bacause sometimes the template matching is automatic and based on the
function argument list, and the template arguments are many, and I don't
want to write it explicitely, because is useless, dirty and error prone.
Simply that.
All you need to do is to use the function itself to introduce the
type. With introduction of TR1 it's going to be very easy, AFAIUI:

std::tr1::result_of<foo<int obj = foo<int>();

Meanwhile you can probably use 'Boost'.
Thank you for the suggestion. Actually, I could use traits in a similar
way, but I would avoid to explicitely list the template arguments.
>>If it's slicing you're trying to
avoid, your 'foo' has already sliced everything, binding a reference
to it is pointless.
Why has sliced? I returned a 'Derived', that's all. Binding a
'Derived' with a 'Base' reference it's illegal (I don't think)? It
produces slicing?

No. Binding a reference does not introduce slicing. Read what I wrote
more carefully, and think about it before replying.
Yes, I answered like that because I can't understand where the slicing
could take place in my original program. Since it don't seem to me that
foo could cause slicing (maybe i don't have yet well understood your
initial comment), I was asking if some other piece of code were illegal.
Now, think about it. Next time somebody makes your 'foo<int>' return
a type that is not a descendant of 'Base'. What do you do then?
Compile-time error? I want the reference to the correct object because I
want the correct destructor to be called at the end of the reference
variable life, but I *do* want that the return object of the foo method
is derived from a certain type (i.e., sometimes I need to use some
'Base' methods).

That
is why you shouldn't stop mid-stream when making your stuff generic.
If your function relies on some traits template to return a proper
object type, use the same traits to declare the receiving object.

Is there anything else here that needs clarification?
For the reasons above, I want to know that the returned object is
derived from Base, I don't want the stuff to be too generic.

End of all, I still don't understand why the compiler gives me the error
that the variable isn't used. It *is* (in the destructor), and I don't
think my code is unsafe.

Thank you for your patience.

Zeppe
Sep 12 '06 #9
zeppe wrote:
[..]
End of all, I still don't understand why the compiler gives me the
error that the variable isn't used.
Uh... It doesn't give you the *error*. It gives you a *warning*.
Your code is not ill-formed. Just ignore the warning, will you? Just
let it go. Let it be. Forgedaboudit. Disable it using compiler-
specific means (like a command-line switch or a pragma), if you are
startled by its appearing in your compiler output.

It is not a common idiom to return an object, bind it to a reference
and wait till the reference goes out of scope. Yes, it does prolong
the lifetime of the temporary. It's just not used so often, that's
why the compiler writers decided to let you know that you might be
missing something, probably. I am not sure I need to explain to you
the merit of compiler *warnings*, but here is an example:

Blah blah1, &blah2 = somefunction();

blah1.foo();
blah1.foo(); // inteded to say 'blah2.foo()', but made a typo

Here, the compiler warns you of 'blah2' being unused. And it is
unused, for all intents and purposes. Make it const, and it does
change something, but not enough to justify dropping the warning.

Again, I feel a bit strange trying to justify a compiler warning to
you. Contact your compiler makers if you feel that a warning is not
appropriate in that case, and see what they tell you.
It *is* (in the destructor), and
I don't think my code is unsafe.
What makes you think that warning has anything to do with safety?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 12 '06 #10
Victor Bazarov ha scritto:
Here, the compiler warns you of 'blah2' being unused. And it is
unused, for all intents and purposes. Make it const, and it does
change something, but not enough to justify dropping the warning.

Again, I feel a bit strange trying to justify a compiler warning to
you.
For example, I don't understand why:

Derived obj = foo();

doesn't give me any warning, obj being not used, where

const Derived& obj = foo();

does.
>
>It *is* (in the destructor), and
I don't think my code is unsafe.

What makes you think that warning has anything to do with safety?
uhm. You are right. I've noticed that often the compiler is quite
"smart": for instance:

Derived obj = foo();

doesn't give me any warn even if obj is not used (i thought that it were
'cause of the destructor being called), where

int obj = foo2(); // foo2 returns int

does (obj not used). So i've always thought that the compiler warn me
about code that is unsafe, unsafe in other architectures (i.e., some
implicit casts), error-prone (missing parenthesis, etc): but always,
where the code is correct, there is a simple way to make it compile
without warns without changing the program logic.

It's possible that if the compiler warn me about a not used object, in
the optimization removes that object introducing a bug in my program?

Thank you!

Zeppe

Sep 12 '06 #11
zeppe wrote:
[..]
It's possible that if the compiler warn me about a not used object, in
the optimization removes that object introducing a bug in my program?
I strongly doubt that. There are several explicitly allowed types of
optimization the compiler can use, and this is not one of them. No
compiler exists without a flaw, either, so if you find something out
of the ordinary (by using good test cases), contact the compiler vendor
or manufacturer.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 12 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Hafeez | last post by:
I am having real trouble compiling this code http://www.cs.wisc.edu/~vganti/birchcode/codeHier/AttrProj.tgz The attachment shows errors when compiled using the current version of g++ in a...
2
by: atv | last post by:
Hi, is there something wrong with this code? It seems that it crashes at the else { clause, when allocating a second record. Excuse for the indentation, the g_warnings are from gtk. Also, i'm...
30
by: Philippe Bertrand | last post by:
Is this a bug in the C# compiler or CLR runtime? enum MyEnum { ZERO = 0, ONE = 1, TWO = 2 } class Foo { public Foo(string,object) { ... } public Foo(string,MyEnum) { ... } } Foo f = new...
34
by: Bob | last post by:
Hi, The compiler gives Warning 96 Variable 'cmdSource' is used before it has been assigned a value. A null reference exception could result at runtime. Dim cmdSource as SQlClient.SQLDataReader...
83
by: Anonymous | last post by:
Came across some code summarized as follows: char const* MyClass::errToText(int err) const { switch (err) { case 0: return "No error"; case 1: return "Not enough"; case 2: return "Too...
15
by: robert maas, see http://tinyurl.com/uh3t | last post by:
Here's the source: #include <stdio.h> #include <errno.h> main () { char* str = "9999999999"; long long int llin; char* endptr; /* Set by strtoll */ int nch; errno = 0; llin = strtoll(str,...
30
by: Bill Reid | last post by:
#define MAX_VALUES 64 typedef struct { unsigned value_1; double value_2; double value_3; double value_4; } VALUES; typedef struct {
0
by: Grant Edwards | last post by:
I've got a system where I try to install extensions using /usr/local/bin/python setup.py install But, it fails when it tries to use a non-existant compiler path and specs file. I suspect it's...
10
by: questions | last post by:
# include <stdio.h> # include <math.h> int main() { long int x,y; printf("enter an integer\n"); scanf("%d",&x); y=x%pow(10,3);
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.