C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Passing *this as argument to another constructor

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
kelvSYC
Guest





PostPosted: Mon Dec 20, 2004 10:43 am    Post subject: Passing *this as argument to another constructor Reply with quote



For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

--
I am only a mirage.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ivan Vecerina
Guest





PostPosted: Tue Dec 21, 2004 12:52 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote



"kelvSYC" <kelvSYC (AT) no (DOT) email.shaw.ca> wrote

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error.
What error message exactly?

What lead you to the conclusing that passing "this" was causing the error?
Quote:
For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

There are two problems in the code above:
- Bar is used in class Foo before class Bar has been defined.
You need to change the order of the classes and forward-declare
Foo.
- Because Bar has a data member of reference type (Foo& foo),
its instances are not assignable, and you cannot store them
in a vector. You may want to use a pointer instead, internally.

The following shall compile and work ok:

#include
class Foo;

class Bar {
Foo* foo;
public:
Bar(Foo& f) : foo(&f) {}
};

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};



I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Sharad Kala
Guest





PostPosted: Tue Dec 21, 2004 12:54 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote




"kelvSYC" <kelvSYC (AT) no (DOT) email.shaw.ca> wrote in message

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;

What is Bar ? Compiler hasn't seen it so far. Define Bar before Foo, you
will need a forward declaration for Bar to compile.

Quote:
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

There is still another problem. You haven't defined your own copy-assignment
operator. 12.8/12 reads - "
A program is illformed if the class for which a copy assignment operator is
implicitly defined has:
- a nonstatic data member of const type, or
- a nonstatic data member of reference type, or
- a nonstatic data member of class type (or array thereof) with an
inaccessible copy assignment operator,
or
- a base class with an inaccessible copy assignment operator."

Sharad

PS - To be stored in any std container, an object must be properly
assignable and copy-constructible.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
GianGuz
Guest





PostPosted: Tue Dec 21, 2004 12:55 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

kelvSYC wrote:
Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't
see
anything wrong with it. What is wrong with this code?


You have to change something to make it work:

#include
class Foo;

class Bar {

Foo* foo;

public:

Bar(Foo* f) : foo(f) {}

};

class Foo {

std::vector<Bar> bars;

public:

void f() {

for (int i = 0; i < 10; i++) bars.push_back(Bar(this));
}

};

First the Bar class must be declared before Foo because its constructor
was called into Foo and a forward declaration is not enough
to make the compiler happy.
Second you need a forward declaration of Foo because Bar uses it.
Third because of the forward declaration, you can't use a Foo reference
into Bar but you need a pointer to Foo.

Gianguglielmo
[excess quoting deleted --mod]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Krügler (ne Spange
Guest





PostPosted: Tue Dec 21, 2004 12:56 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

Hello "kelvSYC",

kelvSYC schrieb:

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:


class Bar;


Quote:
class Foo {
std::vector<Bar> bars;

This kind of declaration is not guaranteed to work portably. Standard

containers
require complete types as worded by 17.4.3.6. (Note that this constraint
is of course not to
limitiations of templates itself, but an "artifical" limitiation to give
implementors of the C++ library
more freedom). This problem is not fixable if you limit yourself on
value members Bar in
"STL" containers. You could use

std::vector<boost::shared_ptr bars;

instead.

Quote:
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

Even if there were not problem one (v.s.), at least the implementation

of Foo::f would need
the definition of Bar. This problem would be easy to fix, if you delay
your implementation of
Foo::f until Bar has been defined (and thus the type Bar is completed).

Quote:
class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};


Class Bar provides another source of problems (at least considering
"STL" containers), because
it needs to fulfil the Copyability requirement. Note that you could fix
your problem by either
defining manually the copy c'tor and copy assignment op. of Bar (But
that wouldn't solve problem
one) or using a kind of (copyable) handle to Bar's as value types of
your container. One example would
be the usage of std::vector instead of
std::vector<Bar> as explained
above.

Greetings from Bremen,

Daniel Krügler



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Alf P. Steinbach
Guest





PostPosted: Tue Dec 21, 2004 12:58 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

* kelvSYC:
Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

1) The declaration order of the classes.
2) Having a std::vector of non-copyable type.

You can do it like this:

class Foo;

class Bar {
Foo* foo; // No ownership, just a ref.
public:
Bar(Foo& f) : foo(&f) {}
};

class Foo {
std::vector public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Tue Dec 21, 2004 12:58 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

kelvSYC wrote:
Quote:
class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

It would have been helpful to know what exactly the error was. However,
using my Crystal Ball(tm), I determined the cause of your bad karma: class
'Bar' needs to be defined before it can be used in class 'Foo'. However,
class 'Bar' needs class 'Foo' to be declared. So, the layout needs to look
like this:

// declare Foo
class Foo;
// define Bar
class Bar{ Foo& foo; ... };
// define Foo
class Foo{ vector
Hovever, you still have a problem: in order to store things in a vector,
they have to be copyable and assignable, which your class isn't because it
has a reference. This isn't easily patched, this needs a redesign rather.
Just a hint that might be useful or not: boost::enable_shared_from_this.

Uli

--
FAQ: http://parashift.com/c++-faq-lite/

/* bittersweet C++ */
default: break;

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michael Jørgensen
Guest





PostPosted: Tue Dec 21, 2004 12:59 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote


"kelvSYC" <kelvSYC (AT) no (DOT) email.shaw.ca> wrote

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));

Replace the above line with the following two lines:
Bar bar(*this);
for (int i = 0; i < 10; i++) bars.push_back(bar);

The compiler barks over the *second* line, so there is nothing wrong in the
way Bar objects are constructed.

However, when use a std::vector you need to supply a default constructor.
Your Bar class does not have one.

-Michael.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Bob Hairgrove
Guest





PostPosted: Tue Dec 21, 2004 10:25 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

On 20 Dec 2004 05:43:16 -0500, kelvSYC <kelvSYC (AT) no (DOT) email.shaw.ca>
wrote:

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

It would be nice to see the error message.

Anyway, the definition of Bar has to be seen before you can write
std::vector reference to Foo in Bar.

Otherwise, I don't see anything wrong ... perhaps you could post a
more complete example?

--
Bob Hairgrove
[email]NoSpamPlease (AT) Home (DOT) com[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Tue Dec 21, 2004 10:27 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

kelvSYC <kelvSYC (AT) no (DOT) email.shaw.ca> writes:

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

Please *always* copy&paste the errors that you have a question about
when posting to a newsgroup.


Quote:
class Foo {
std::vector<Bar> bars;

At this point, the name Bar isn't defined (and not even
declared). Standard Library templates require their parameter types to
be complete, though.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Andrew Koenig
Guest





PostPosted: Tue Dec 21, 2004 10:27 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

"kelvSYC" <kelvSYC (AT) no (DOT) email.shaw.ca> wrote


Quote:
class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

Bar has a member of reference type, so the compiler doesn't generate
operator=, which means that vector own, as well as Bar::Bar(const Bar&).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Branimir Maksimovic
Guest





PostPosted: Tue Dec 21, 2004 10:33 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote


kelvSYC wrote:
Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't
see
anything wrong with it. What is wrong with this code?


First, class Foo is defined before Bar so that wouldn't compile
anyways.
If you write this differently:

Quote:
class Bar {
Foo& foo;
class Foo& foo; // must forward declare class Foo
public:
Bar(Foo& f) : foo(f) {}
};

class Foo {
std::vector public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

Error is obvious. Compiler can't use default assignment operator
on reference to incomplete type.
This does not have anything to do with passing reference
to *this.

Greetings, Bane.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Antoun Kanawati
Guest





PostPosted: Tue Dec 21, 2004 10:34 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

kelvSYC wrote:
Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

It would help if you told us what the error was.

The above code is not valid; the std::vector the class Bar is not defined or declared yet. Same goes for Bar(*this).

This has nothing to do with *this.

You're making forward references to the class Bar. This sort of stuff
works in Java, but not in C++.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Falk Tannhäuser
Guest





PostPosted: Wed Dec 22, 2004 2:39 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

kelvSYC wrote:
Quote:
class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

This would spit out an error (on at least gcc anyways), and I don't see
anything wrong with it. What is wrong with this code?

std::vector needs its elements to support copy construction and
assignment, and your class Bar has no assignment operator (neither
compiler-generated nor user-supplied) since it has a reference
member Foo& foo - references can't be reassigned once they are
constructed.
Possible solution : make foo a pointer to Foo - pointers can be
reassigned. You need to think about ownership and lifetime of
the pointed object, though.

Another possible issue is with order of declaration: To instantiate
std::vector for defining the foo member in Bar (be it a pointer or a reference)
it is enough for class Foo to be declared. Thus the order should
probably be:

class Foo; // Declaration, not a definition


class Bar
{
Foo* foo;
....
}; // Here Bar is completely defined


class Foo // Here begins the definition of Foo
{
std::vector<Bar> bars; // OK to use Bar here
....
};


Falk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Talbut
Guest





PostPosted: Wed Dec 22, 2004 2:40 am    Post subject: Re: Passing *this as argument to another constructor Reply with quote

"kelvSYC" <kelvSYC (AT) no (DOT) email.shaw.ca> wrote

Quote:
For some reason, passing this as an argument to another class'
constructor spits out an error. For example:

class Foo {
std::vector<Bar> bars;
public:
void f() {
for (int i = 0; i < 10; i++) bars.push_back(Bar(*this));
}
};

class Bar {
Foo& foo;
public:
Bar(Foo& f) : foo(f) {}
};

I'm new to the standard, so this is partly a test of my ability to
make sense of it, but:

Section 8.3.2/4 states that "A reference shall be initialized to refer
to a valid object or function." and section 3.8./1 states that "The
lifetime of an object of type T begins when, if T is a class type with
a non-trivial constructor, the constructor call has completed".
I can't actually find a definition of "a valid object", but I think it
reasonable to assume it means one whose lifetime has begun - hence you
can't take a reference to something until it's constructor has
complete.

It would help if you'd said what the error you got was, that would
help to clarify whether this is the correct reasoning.

--
J.T.
Please reply via the newsgroup.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.