473,657 Members | 2,582 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Temporary objects as constructor arguments?

Hi,

A friend and I have recently had trouble getting code to compile when
using temporary objects in constructors. A minimal example is below:

This code fragment is used to construct seven ROD objects and run
their doSomething() method (which is trivial).

As far as we can tell, all seven methods should successfully construct a
ROD object using temporary objects as constructor parameters, but using
g++ 3.2.3 only the first 4 actually succeed. The remainder seem to be
treated as constructing/declaring(?) a function pointer and so the attempt
to call a method fails for these.

Confusingly, some of the approaches which fail under g++ do compile
successfully using MicroSoft Visual C++ 6.0: can anyone enlighten us as to
whether this is a failing in our understanding of the language or a bug in
g++? (probably the first!)

// Minimal test case:

#include <iostream>

typedef unsigned int U;

class T {
public:
T() {};
T( const U & ) { }
};

class ROD {
public:
ROD(const T &) { }
void doSomething() const {
std::cout << "Hello -- I am a ROD" << std::endl;
}
};

class CC {
public:
void doSomethingElse () {

ROD rod1 = ROD( T( t() ) ) ; // does what I want -- makes a ROD
ROD rod2 ( T( this->t() ) ) ; // does what I want -- makes a ROD
ROD rod3 ( *(new T() ) ) ; // does what I want -- makes a ROD
ROD rod4 ( T( 0 ) ) ; // does what I want -- makes a ROD

rod1.doSomethin g(); // succeeds rod2.doSomethin g();
// succeeds rod3.doSomethin g(); // succeeds
rod4.doSomethin g(); // succeeds

/*
ROD rod5 ( T( t() ) ) ; // doesn't do what I want (*) ROD
rod6 ( ROD( T( t() ) )); // doesn't do what I want (*) ROD
rod7 ( T() ) ; // doesn't do what I want (*)

rod5.doSomethin g(); // doesn't compile
rod6.doSomethin g(); // doesn't compile
rod7.doSomethin g(); // doesn't compile
*/

// (*) At these statements, funtion pointers seem to be declared :(
}
T t() const { return T(0); }
};

int main () {
CC cc;
cc.doSomethingE lse();
return 0;
}
Jul 22 '05 #1
5 1501
Andy Buckley wrote:
A friend and I have recently had trouble getting code to compile when
using temporary objects in constructors. A minimal example is below:

This code fragment is used to construct seven ROD objects and run
their doSomething() method (which is trivial).

As far as we can tell, all seven methods should successfully construct a
ROD object using temporary objects as constructor parameters, but using
g++ 3.2.3 only the first 4 actually succeed. The remainder seem to be
treated as constructing/declaring(?) a function pointer and so the attempt
to call a method fails for these.
The last two are not declarations at all. The fifth is a declaration.
See below.
Confusingly, some of the approaches which fail under g++ do compile
successfully using MicroSoft Visual C++ 6.0: can anyone enlighten us as to
whether this is a failing in our understanding of the language or a bug in
g++? (probably the first!)
It's a bug in your understanding of the language.

// Minimal test case:

#include <iostream>

typedef unsigned int U;

class T {
public:
T() {};
T( const U & ) { }
};

class ROD {
public:
ROD(const T &) { }
void doSomething() const {
std::cout << "Hello -- I am a ROD" << std::endl;
}
};

class CC {
public:
void doSomethingElse () {

ROD rod1 = ROD( T( t() ) ) ; // does what I want -- makes a ROD
ROD rod2 ( T( this->t() ) ) ; // does what I want -- makes a ROD
ROD rod3 ( *(new T() ) ) ; // does what I want -- makes a ROD
ROD rod4 ( T( 0 ) ) ; // does what I want -- makes a ROD

rod1.doSomethin g(); // succeeds rod2.doSomethin g();
// succeeds rod3.doSomethin g(); // succeeds
rod4.doSomethin g(); // succeeds

/*
ROD rod5 ( T( t() ) ) ; // doesn't do what I want (*) ROD
It's a declaration. See FAQ 10.2 and search the Google Groups for
similar problems people have been asking about since Adam.
rod6 ( ROD( T( t() ) )); // doesn't do what I want (*) ROD
Huh? You begin a statement with it, but 'rod6' is undefined.
rod7 ( T() ) ; // doesn't do what I want (*)
'rod7' is undefined as well.

Did you miss "ROD " in front of the two last statements? It seems
to suggest that instead of copying and pasting the code from your
C++ source file, you typed it in. Who knows how many more mistakes
you've made while doing that...

rod5.doSomethin g(); // doesn't compile
rod6.doSomethin g(); // doesn't compile
rod7.doSomethin g(); // doesn't compile
*/

// (*) At these statements, funtion pointers seem to be declared :(
}
T t() const { return T(0); }
};

int main () {
CC cc;
cc.doSomethingE lse();
return 0;
}


V
Jul 22 '05 #2
On Wed, 25 Aug 2004 18:27:23 +0100, Victor Bazarov wrote:
Andy Buckley wrote:

As far as we can tell, all seven methods should successfully construct
a ROD object using temporary objects as constructor parameters, but
using g++ 3.2.3 only the first 4 actually succeed. The remainder seem
to be treated as constructing/declaring(?) a function pointer and so
the attempt to call a method fails for these.


The last two are not declarations at all. The fifth is a declaration.

ROD rod5 ( T( t() ) ) ; // doesn't work


It's a declaration. See FAQ 10.2 and search the Google Groups for
similar problems people have been asking about since Adam.


Have looked at FAQ 10.2 and while rod5 is definitely being treated as a
declaration of a function which returns a ROD, I'm confies as to why:
the parentheses contain a real (if temporary) instantiation of a T object
rather than a type declaration. FAQ 10.2 only seems to describe the case
analogous to saying

ROD rod5();

which I can understand as declaring a function. Equivalently,

ROD rod5( T t( U u() ) );

according to the C++ function declaration grammar matches the definition
of a set of nested function declarations (however crazy the idea might
be). But when t() should return a concrete instatiation of a T object, I
would have expected this to fail to match the function declaration.

A clearer repost of the code without the copy-construction and
with the erroneous line-wrapping hopefully sorted is below. If you can
spare a moment to explain just what's going on, in particular on the
highlighted line, we'd both be very happy! Thanks.
// Reposted code:

#include <iostream>

typedef unsigned int U;

class T {
public:
T( const U & ) { }
};

class ROD {
public:
ROD(const T &) { }
void doSomething() const {
std::cout << "Hello -- I am a ROD" << std::endl;
}
};

class CC {
public:
void doSomethingElse () {

ROD rod5( T( u() ) ); // *** line of interest
rod5.doSomethin g(); // doesn't compile since it
// thinks rod5 is a function ptr
// of type ROD ()(T (*)())
}

U u() const { return 0; }
};

int main () {
CC cc;
cc.doSomethingE lse();
return 0;
}
Jul 22 '05 #3
Andy Buckley wrote:
On Wed, 25 Aug 2004 18:27:23 +0100, Victor Bazarov wrote:

Andy Buckley wrote:
As far as we can tell, all seven methods should successfully construct
a ROD object using temporary objects as constructor parameters, but
using g++ 3.2.3 only the first 4 actually succeed. The remainder seem
to be treated as constructing/declaring(?) a function pointer and so
the attempt to call a method fails for these.


The last two are not declarations at all. The fifth is a declaration.


ROD rod5 ( T( t() ) ) ; // doesn't work


It's a declaration. See FAQ 10.2 and search the Google Groups for
similar problems people have been asking about since Adam.

Have looked at FAQ 10.2 and while rod5 is definitely being treated as a
declaration of a function which returns a ROD, I'm confies as to why:
the parentheses contain a real (if temporary) instantiation of a T object
rather than a type declaration. FAQ 10.2 only seems to describe the case
analogous to saying

ROD rod5();

which I can understand as declaring a function. Equivalently,

ROD rod5( T t( U u() ) );

according to the C++ function declaration grammar matches the definition
of a set of nested function declarations (however crazy the idea might
be). But when t() should return a concrete instatiation of a T object,


Why?

K k(blah)

is either an object declaration or a function declaration depending on
what 'blah' is. If 'blah' is another declaration (or is empty), then 'k'
is a function that takes one argument (or nothing) and returns K.
I
would have expected this to fail to match the function declaration.
Well, that's usually due to one's lack of experience with declarations.
No big deal, we are all learning.

A clearer repost of the code without the copy-construction and
with the erroneous line-wrapping hopefully sorted is below. If you can
spare a moment to explain just what's going on, in particular on the
highlighted line, we'd both be very happy! Thanks.
// Reposted code:

#include <iostream>

typedef unsigned int U;

class T {
public:
T( const U & ) { }
};

class ROD {
public:
ROD(const T &) { }
void doSomething() const {
std::cout << "Hello -- I am a ROD" << std::endl;
}
};

class CC {
public:
void doSomethingElse () {

ROD rod5( T( u() ) ); // *** line of interest
rod5.doSomethin g(); // doesn't compile since it
// thinks rod5 is a function ptr
// of type ROD ()(T (*)())
Yes, that's the behaviour according to the Standard.

First of all, anything that can be interpreted as a declaration, shall
be interpreted as a declaration. That's the rule. It resolves ambiguity
that otherwise exists in these particular cases.

Second, if it's a declaration, how do you interpret it? Begin from what
looks like a variable name, 'rod5'. It has a parenthesis right next to
it. If what's inside the parentheses is not an expressions, it is very
likely another declaration, then 'rod5' is a function. So, let's try to
interpret what's inside the parentheses.

You seem to understand the FAQ 10.2, so, I'll build my explanation based
on that. Imagine that instead of

int a;

you have

int (a);

Does it change anything? No. The parentheses surrounding the variable
name are superfluous in that case, and change nothing. So

int (a);

is equivalent to

int a;

.. If that's so, then I can always remove the parentheses that follow the
type name and the declaration will mean the same, right? Now, if I say

int(a());

what is it? Nothing else but

int a();

(after removing the top-level parentheses). Now replace 'int' with 'T'
and 'a' with 'u'. What do you get?

T(u());

What is it? A declaration of 'u', that is a function that takes no args
and returns an value of type T. Now simply put that declaration inside
the parentheses of a function declaration and you get

ROD rod5(T(u()));

which is equivalent to

ROD rod5( T u() );

which means 'rod5' is a function that takes one argument of type [pointer
to function that takes no arguments and returns T] and returns ROD.

* * *

Now, the question is, "how do we fix this"? This is one way:

ROD rod5 = ROD(T(u()));

which would generate an error because 'u' is undefined. You probably
meant

ROD rod5 = ROD(T(U()));

Another way is to use real objects of type U and T:

U u;
T t(u);
ROD rod5(t);
}

U u() const { return 0; }
};

int main () {
CC cc;
cc.doSomethingE lse();
return 0;
}


Victor
Jul 22 '05 #4

Hi Victor,

(by the way, I'm the friend Andy referred to)

First I'd like to thank you for your most recent and fullest answer
to this thread. It has been very helpful in clarifying our original
misunderstandin g, and I've definitely learned some things.

If nothing else happens to this thread I will consider it usefully
closed.

Nevertheless, I don't think any harm will come if I try to paraphrase
what you have already said (a) to make sure that we have understood
everything correctly, and (b) to check that a small (almost
throw-away) remark you made near the foot of the last message is
indeed nothing more than a simple slip -- and not something more
important.

So here goes my paraphrasing:

The first and most important thing you said (I'll call it (1)) is:
First of all, anything that can be interpreted as a declaration,
shall be interpreted as a declaration. That's the rule. It
resolves ambiguity that otherwise exists in these particular cases.
The above comment particularly relevant to the line I have
labelled (3) below:

class CC {
void doSomething();
U u(); // (2)
};
void CC::doSomething () {
ROD rod5(T(u())); // (3)
};

which was found within the definition of a method of a class CC that
ALSO DEFINED A METHOD u() (labelled (2) above). [ In the above
fragment I have separated the definition of the doSomething method
from its declaration for reasons that will hopefully become clearer
shortly. ]

The other thing you carefuly explained (but which I don't copy here)
was to explain how a line like (3) could correctly be interpreted IN
THE ABSENCE of a declaration such as (2) as a function declaration.

Our original mistake was to believe that the declaration of u() in
(2) would (within the scope of definitions of methods of CC such as
in location (3)) be sufficient to prevent it later being interpreted
as a declaration for something else.

Your comment (1) tells us WHY we were wrong:

Your comment (1) tells us that although (2) declared our "intention"
(whatever that means!) for how we wanted "u()" to be interpreted, the
mere fact that it COULD be interpreted in (3) as a function
declaration was sufficient to REQUIRE it to be interpreted so. Fair
enough. There must, of course, be a rule.

So if everything I have said above is correct, then I am now a happy
man as I now understand the language a bit better!

Thanks Victor.

I only re-iterate the above because of the throw-away remark I
alluded to earlier that we found at the end of your last mail which
casts just a tiny doubt in my mind, but which probably signifies
nothing much:
Now, the question is, "how do we fix this"? This is one way:
ROD rod5 = ROD(T(u())); // (4)
which would generate an error because 'u' is undefined.


Now you can see why I (in this posting) separated the implementation
of CC::doSomething () from its declaration in the class definition --
because this way I think it's easier to see that 'u' (or at least
CC::u) really IS defined at the point at which the compiler tries to
attack the internals of doSomething. Or at least we intended it to
be defined! As far as I know, the status of the definition of CC::u
would not be affected by moving the implementation of doSomething to
within the class body (even if doSomthing happened to be declared
ahead of u()), and so I presume that what I've said here also applies
equally to what we expected from our last posting.

So I'm going to assume that you simply didn't spot the u()
declaration in our CC class (an understandable mistake to make given
how we managed to mess up the original posting in more than one
way!), and that as a result the status of (4) moves from failing to
fix the problem, to actually being a good problem fix!

Which is a good thing!

So again, thank you for your time.

Christopher

Jul 22 '05 #5
"Christophe r Lester" <le****@hep.phy .cam.ac.uk> wrote...
[...]
You got it right.
I only re-iterate the above because of the throw-away remark I
alluded to earlier that we found at the end of your last mail which
casts just a tiny doubt in my mind, but which probably signifies
nothing much:
Now, the question is, "how do we fix this"? This is one way:
ROD rod5 = ROD(T(u())); // (4)
which would generate an error because 'u' is undefined.
Now you can see why I (in this posting) separated the implementation
of CC::doSomething () from its declaration in the class definition --
because this way I think it's easier to see that 'u' (or at least
CC::u) really IS defined at the point at which the compiler tries to
attack the internals of doSomething. Or at least we intended it to
be defined! As far as I know, the status of the definition of CC::u
would not be affected by moving the implementation of doSomething to
within the class body (even if doSomthing happened to be declared
ahead of u()), and so I presume that what I've said here also applies
equally to what we expected from our last posting.

So I'm going to assume that you simply didn't spot the u()
declaration in our CC class (an understandable mistake to make given
how we managed to mess up the original posting in more than one
way!), and that as a result the status of (4) moves from failing to
fix the problem, to actually being a good problem fix!


That's the ticket. I didn't pay too close attention to the fact
that 'u' was another member function. I thought (incorrectly) that
"u()" was a slip-up by Andy, who meant to write "U()".

Which is a good thing!


Depends on how you look at it, don't it?

V
Jul 22 '05 #6

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

Similar topics

49
2870
by: Steven Bethard | last post by:
I promised I'd put together a PEP for a 'generic object' data type for Python 2.5 that allows one to replace __getitem__ style access with dotted-attribute style access (without declaring another class). Any comments would be appreciated! Thanks! Steve ----------------------------------------------------------------------
5
1690
by: White Wolf | last post by:
Hi, I would like to double check how long a temporary returned by a function lives? Suppose I have an instance of a class type C, which has a member function returning some sort of wrapper-decorator by value - thereby creating an unnamed temporary. Assuming I start using the temporary (by calling its members) in the same expression, can I assume that it will live long enough to serve those calls?
5
1288
by: szaki | last post by:
Hi, I have tested the piece of code below on Intel ICC and GCC compilers, both produce the same result. -------------------- CODE: -------------------- #include <iostream>
7
11557
by: b83503104 | last post by:
Previously, when my constructor had no arguments, I used this to declare my objects: MyClass myObject; Now, my constructor has arguments (MyClass::MyClass(int someVariable)), how do I declare my objects? I tried MyClass myObject(100); and
3
3027
by: sven.suursoho | last post by:
Hello, In main(), the first output API is what I try to achieve. Unfortunately it fails, printing first string as pointer instead of human readable message. Tried to initialize str(""), set new buffer etc, but nothing worked. Ideas? Also might use another internal construct, only API is needed and requirement to reuse existing std::ostream inserters.
5
3710
by: wshaer | last post by:
Hi This is the task: and these are my classes: public class Engine{ // Declare the varibles
11
3247
by: MikeT | last post by:
This may sound very elementary, but can you trap when your object is set to null within the object? I have created a class that registers an event from an object passed in the constructor. When my object is destroyed, I want my object to un-register this event. If I don't then the object would never be destroyed until the object I passed in the constructor is destroyed. I have implemented a Dispose(), Dispose(bool), and ~Finalize...
3
12882
by: daniell | last post by:
/* Triangle.cpp */ // Use a pure virtual function. #include <iostream> #include <cstring> using namespace std;
3
2260
by: RainBow | last post by:
I understand that a compiler synthesises a default constructor if none is provided by the user ( of course depending on the situation if synthesis of such c'tor is actually needed in the program e.g if vptr is needed, default c'tor must be synthesised by compiler). In the class Temporary below, there is no reason why a compiler should synthesise a default c'tor. class Temporary {
0
8392
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8732
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8503
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7324
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6163
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5632
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
1
2726
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1953
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1611
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.