Class with functions that return STL containers with incomplete types

M

massysett

Greetings,

Having classes with member objects that have STL containers of objects
whose definitions are incomplete results in undefined behavior. See
for example:

http://www.ddj.com/database/184403814#8
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.14

I am wondering: is it okay to have member functions that return an STL
container with an incomplete type? My member objects do not contain
incomplete types. For instance, would the following code be OK?
Thanks. --Omari

#include <boost/shared_ptr.hpp>
#include <vector>

class HasSelf
{
public:
HasSelf(std::vector<HasSelf>& contents);
std::vector<HasSelf> getContents() const;

private:
std::vector<boost::shared_ptr<HasSelf> > _contents;
};
 
C

Christopher

Greetings,

Having classes with member objects that have STL containers of objects
whose definitions are incomplete results in undefined behavior. See
for example:

http://www.ddj.com/database/1844038.../c++-faq-lite/misc-technical-issues.html#faq-...

I am wondering: is it okay to have member functions that return an STL
container with an incomplete type? My member objects do not contain
incomplete types. For instance, would the following code be OK?
Thanks. --Omari

#include <boost/shared_ptr.hpp>
#include <vector>

class HasSelf
{
public:
HasSelf(std::vector<HasSelf>& contents);
std::vector<HasSelf> getContents() const;

private:
std::vector<boost::shared_ptr<HasSelf> > _contents;

};

Why in the world would you make a class that contains multiple
instances of itself instead of a class for an element and a separate
class that contains elements?

Also, in order to create a vector of objects, those objects have to
have a default copy constuctor, which the HasSelf class does not
have.
 
V

Victor Bazarov

Christopher said:
Why in the world would you make a class that contains multiple
instances of itself instead of a class for an element and a separate
class that contains elements?

It could be the way to organize a hierarchical structure of objects.
Also, in order to create a vector of objects, those objects have to
have a default copy constuctor, which the HasSelf class does not
have.

That's not necessary. The objects have to be Copy-Constructible
and Assignable. Only if you create the vector using the default
constructor without the prototype object, the object needs to be
Default-Constructible.

V
 
O

Omari Norman

Why in the world would you make a class that contains multiple
instances of itself instead of a class for an element and a separate
class that contains elements?

I am representing a recipe, which has ingredients. One of the
ingredients can be another recipe. It's less flexible to have two
kinds of classes here (e.g. "recipe" and "ingredient").
Also, in order to create a vector of objects, those objects have to
have a default copy constuctor, which the HasSelf class does not
have.

Yes, sorry for not putting that in the illustration.
 
O

Omari Norman

#include <boost/shared_ptr.hpp>
#include <vector>
class HasSelf
{
public:
HasSelf(std::vector<HasSelf>& contents);
std::vector<HasSelf> getContents() const;
private:
std::vector<boost::shared_ptr<HasSelf> > _contents;

Yes, sorry for not putting that in the illustration.

Actually, my illustration didn't need that. Objects in a vector need
to be copyable; HasSelf is copyable. The compiler made a copy
constructor which works fine for this illustration.
 
J

Joe Greer

Greetings,

Having classes with member objects that have STL containers of objects
whose definitions are incomplete results in undefined behavior. See
for example:

http://www.ddj.com/database/184403814#8
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq- 39
.14

I am wondering: is it okay to have member functions that return an STL
container with an incomplete type? My member objects do not contain
incomplete types. For instance, would the following code be OK?
Thanks. --Omari

#include <boost/shared_ptr.hpp>
#include <vector>

class HasSelf
{
public:
HasSelf(std::vector<HasSelf>& contents);
std::vector<HasSelf> getContents() const;

private:
std::vector<boost::shared_ptr<HasSelf> > _contents;
};

shared_ptr<> does not require that the class be complete, but in this
case, shared_ptr itself is complete. Therefore you can have a vector of
shared_ptrs to an incomplete class. I assume that since the member is a
vector of shared_ptrs, that the other vectors are also vectors of
shared_ptrs?


joe
 
V

Victor Bazarov

Joe said:
shared_ptr<> does not require that the class be complete, but in this
case, shared_ptr itself is complete. Therefore you can have a vector
of shared_ptrs to an incomplete class. I assume that since the
member is a vector of shared_ptrs, that the other vectors are also
vectors of shared_ptrs?

That would require at least creating them using some kind of memory
management (like 'new'), which is more expensive and less efficient
than letting a 'vector' handle the entire array of those. Of course,
if legality is the primary concern, it seems like the only viable
solution...

V
 
J

James Kanze

innews:315ae592-2b90-4285-b1b3-b4ffb6671ec1@h11g2000prf.googlegroups.com:
shared_ptr<> does not require that the class be complete, but
in this case, shared_ptr itself is complete. Therefore you
can have a vector of shared_ptrs to an incomplete class. I
assume that since the member is a vector of shared_ptrs, that
the other vectors are also vectors of shared_ptrs?

If I understand correctly, the vector isn't his problem. He
knows that that's OK. The problem is the parameter of the
constructor and the return value of getContents.

If I interpret the situation correctly: according to the
standard, it is undefined behavior to instantiate vector with an
incomplete type (and HasSelf only becomes complete at the
closing brace). However (§14.7.1/1), "[...], the class template
is implicitly instantiated when the specialization is referenced
in a context that requires a completely-defined object type or
when the completeness of the class type affects the semantics of
the program." Since a reference or a return value may be an
incomplete type; the compiler should not instantiate the
template in this case, so the code is correct. (On the other
hand, converting between vector< HasSelf > and vector<
shared_ptr< HasSelf > > is typically not a trivial operation.
Quite frankly, I think I'd just use a std::vector< HasSelf >* as
the member.)
 

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

Forum statistics

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

Latest Threads

Top