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 

Typedef forward reference
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Ralph Shnelvar
Guest





PostPosted: Sun Oct 26, 2003 5:07 am    Post subject: Typedef forward reference Reply with quote



Consider

typedef std::vector<somethingUnknown> somethingUnknown_vector;

where somethingUnknown is a complicated type in some header file that I do
_not_ wish to include in the module under consideration.



Now let's say that I want to define/declare

void somefunc(somethingUnknown_vector& arg)
{
// someOtherFunc is defined in another module and that
// module understands the typedef somethingUnknown_vector.
someOtherFunc(arg);
}

clearly, I should be able to create a forward declaration for
somethingUnknown_vector.

How do I do it?



It is illegal to say

// Forward declaration
class somethingUnknown_vector;

because somethingUnknown_vector is not a class.

Nor can I say
// Forward declaration
class somethingUnknown;
typedef std::vector<somethingUnknown> somethingUnknown_vector;
for too many reasons to list.


So, Steve, how can I do it?

Ralph

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





PostPosted: Sun Oct 26, 2003 11:10 am    Post subject: Re: Typedef forward reference Reply with quote



"Ralph Shnelvar" <ralphs (AT) dos32NoSpaM (DOT) com> wrote in message

Quote:
typedef std::vector<somethingUnknown> somethingUnknown_vector;

It is illegal to say

// Forward declaration
class somethingUnknown_vector;

because somethingUnknown_vector is not a class.

Can you make somethingUnknown_vector a class? It's a very practical
solution, and works. You can derive publicly from std::vector<...> or use
derive privately and provide forwarding functions.


Quote:
Nor can I say
// Forward declaration
class somethingUnknown;
typedef std::vector<somethingUnknown> somethingUnknown_vector;
for too many reasons to list.

What are the reasons?

The following is legal

class somethingUnknown;
typedef std::vector<somethingUnknown *> somethingUnknown_vector;

But the vector<T*>'s destructor does not delete the pointed-to objects, and
the copy constructor and operator= do not copy the pointed to objects -- so
in other words we have a memory leak.

I suspect the following should be legal

class somethingUnknown;
typedef std::vector<boost::shared_ptr
somethingUnknown_vector;

Finally, you can make class somethingUnknown short and sweet by using the
pointer to implementation concept. Including somethingUnknown.hpp will
hardly add to the compile time.

// somethingUnknown.hpp
#include <memory>
class somethingUnknown {
struct Imp;
std::auto_ptr<Imp> imp;
public:
somethingUnknown();
somethingUnknown(const somethingUnknown&);
somethingUnknown& operator=(const somethingUnknown&);
~somethingUnknown();
};

// somethingUnknown.cpp
#include "somethingUnknown.hpp"
#include ...
#include ...
#include ...
#include ...
#include ...
struct somethingUnknown::Imp {
};
/* etc */

Quote:
So, Steve, how can I do it?

Who is Steve?

--
+++++++++++
Siemel Naran


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

Back to top
Ralph Shnelvar
Guest





PostPosted: Sun Oct 26, 2003 7:14 pm    Post subject: Re: Typedef forward reference Reply with quote



Dear Siemel:

"Siemel Naran" <SiemelNaran (AT) REMOVE (DOT) att.net> wrote:

Quote:
"Ralph Shnelvar" <ralphs (AT) dos32NoSpaM (DOT) com> wrote in message

typedef std::vector<somethingUnknown> somethingUnknown_vector;

It is illegal to say

// Forward declaration
class somethingUnknown_vector;

because somethingUnknown_vector is not a class.

Can you make somethingUnknown_vector a class? It's a very practical
solution, and works. You can derive publicly from std::vector<...> or use
derive privately and provide forwarding functions.

Of course I _could_ do many things. I don't want to do that. I'm trying to
determine if C++'s syntax can be made to do what I think is reasonable:
create a reference to an unknown type where that type is a template.

Quote:


Nor can I say
// Forward declaration
class somethingUnknown;
typedef std::vector<somethingUnknown> somethingUnknown_vector;
for too many reasons to list.

What are the reasons?

The reasons are:
1) std::vector<somethingUnknown> requires that somethingUnknown be declared
as something other than a forward declaration.
2) somethingUnknown may not e a class. It might be a struct ... or worse a
"built-in class" like "int".

Quote:

The following is legal

class somethingUnknown;
typedef std::vector<somethingUnknown *> somethingUnknown_vector;

But the vector<T*>'s destructor does not delete the pointed-to objects, and
the copy constructor and operator= do not copy the pointed to objects -- so
in other words we have a memory leak.

I suspect the following should be legal

class somethingUnknown;
typedef std::vector<boost::shared_ptr somethingUnknown_vector;

I haven't tried it ... and maybe it would work. According to the Boost
documentation, if I use
boost::shared_ptr then somethingUnknown can be an incomplete type.

Interesting.

Quote:

Finally, you can make class somethingUnknown short and sweet by using the
pointer to implementation concept. Including somethingUnknown.hpp will
hardly add to the compile time.

// somethingUnknown.hpp
#include <memory
class somethingUnknown {
struct Imp;
std::auto_ptr public:
somethingUnknown();
somethingUnknown(const somethingUnknown&);
somethingUnknown& operator=(const somethingUnknown&);
~somethingUnknown();
};

// somethingUnknown.cpp
#include "somethingUnknown.hpp"
#include ...
#include ...
#include ...
#include ...
#include ...
struct somethingUnknown::Imp {
};
/* etc */

Well, I already know how to work around the problem (but I thank you for
taking the time to point all of this out. I did learn a few new things).
What I want to do, though, is figure out how to get the declaration right so
that I don't have to work around the problem.

Quote:

So, Steve, how can I do it?

Who is Steve?

Steve is Steve Heller, author of the "Who's Afraid of C++" series. He's a
friend and he recommended that I read the FAQ and then post here because he
didn't have the answer off the top of his head and he's really busy working
on various projects.

So I "reposted" to comp.lang.c++.moderated (after plowing through the FAQ as
Steve suggested) but I forgot to trim off the last line. Steve said that he
didn't think my question had been posted before and he didn't think it was
in the FAQ.

Anyway, there is an obscure statement in
http://www.goingware.com/tips/parameters/notrequired.html
- - - -
Finally, you cannot give forward references for templates at all. I just
think that is a real drag. It is especially a problem for group software
development where a template library is being developed in parallel with the
rest of the application - each template's header must be #included in each
header file that mentions the template, so templates contribute more to
growth of compile time and dependencies than they should have to.
- - - -

I don't know if this applies to my particular question.

It just seems to me that the ability to specify a template as an incomplete
type should be something that C++ should be able to do.

Ralph

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

Back to top
Siemel Naran
Guest





PostPosted: Mon Oct 27, 2003 12:02 am    Post subject: Re: Typedef forward reference Reply with quote

"Ralph Shnelvar" <ralphs (AT) dos32NoSpaM (DOT) com> wrote in message

Quote:
Of course I _could_ do many things. I don't want to do that. I'm trying
to
determine if C++'s syntax can be made to do what I think is reasonable:
create a reference to an unknown type where that type is a template.

Well, I don't think it is possible. Some compilers may accept what you
want,

#include <vector>
class U;
typedef std::vector<U> vector;
void f(vector& v);

We had a discussion about this a long time ago, and I'm not sure what the
final answer was. I think it was deemed illegal because the destructor of
vector may require the destructor of U to exist (ie. be accessible), and
this is not possible with forward declaration.

Failing that, you can try any of the workarounds I gave.


Quote:
It just seems to me that the ability to specify a template as an
incomplete
type should be something that C++ should be able to do.

It can, as in boost::shared_ptr<IncompleteType>. Let's see what the
language experts say about std::vector<IncompleteType>...

--
+++++++++++
Siemel Naran


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

Back to top
Dave Harris
Guest





PostPosted: Tue Oct 28, 2003 1:28 am    Post subject: Re: Typedef forward reference Reply with quote

[email]ralphs (AT) dos32NoSpaM (DOT) com[/email] (Ralph Shnelvar) wrote (abridged):
Quote:
2) somethingUnknown may not e a class. It might be a struct ... or
worse a "built-in class" like "int".

You are allowed to forward declare it as a class and then actually
declare it as a struct.

However, you do need to know whether it is a class rather than an
int or whatever, else there is very little you can do because of
potential overloading issues.

Supposing it were possible to say;
typedef vector<First> FirstVec;
typedef vector<Second> SecondVec;

We could continue:
int proc( FirstVec & ) { return 1; }
int proc( SecondVec & ) { return 2; }

struct First {};
typedef First Second;

and at this point the "One Definition Rule" is violated by proc(),
because FirstVec and SecondVec are different names for the same
type. So the names First and Second have to be introduced properly.


Quote:
Anyway, there is an obscure statement in
http://www.goingware.com/tips/parameters/notrequired.html
- - - -
Finally, you cannot give forward references for templates at all.

I am surprised. It's hard to see why this:

struct Item;
template <typename T> class Vec;
typedef Vec<Item> ItemVec;

wouldn't be supported. Perhaps the author is thinking of standard
templates? We are not allowed to forward-declare things like
std::vector, but that's because they don't belong to us.

If this is truly not supported, can anyone think of a reason it
shouldn't be added to a future version of the standard?

-- Dave Harris, Nottingham, UK

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

Back to top
Dave Harris
Guest





PostPosted: Tue Oct 28, 2003 1:29 am    Post subject: Re: Typedef forward reference Reply with quote

[email]SiemelNaran (AT) REMOVE (DOT) att.net[/email] (Siemel Naran) wrote (abridged):
Quote:
#include <vector
class U;
typedef std::vector void f(vector& v);

We had a discussion about this a long time ago, and I'm not sure
what the final answer was. I think it was deemed illegal because
the destructor of vector may require the destructor of U to exist
(ie. be accessible), and this is not possible with forward
declaration.

In this case the destructor of vector is not instantiated. Indeed,
nor is any vector member function, nor is any instance of vector. I
don't think there should be a problem.

-- Dave Harris, Nottingham, UK

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

Back to top
Ralph Shnelvar
Guest





PostPosted: Tue Oct 28, 2003 1:37 am    Post subject: Re: Typedef forward reference Reply with quote

[snip]

Quote:

#include <vector
class U;
typedef std::vector void f(vector& v);

We had a discussion about this a long time ago, and I'm not sure what the
final answer was. I think it was deemed illegal because the destructor of
vector may require the destructor of U to exist (ie. be accessible), and
this is not possible with forward declaration.


That doesn't seem reasonable.

Consider

// Forward declaration
class X;
...
void
func(X *pX)
{
X *pX2 = pX;
}

That should compile quite nicely.

Now if X was

struct X
{
std::vector<Y> Y_vector;
}

See? All I have to do (as you pointed out) is wrap the std::vector in a
class of its own and things start to compile.

It just seems silly that I would have to wrap a vector in this kind of
syntactic candy in order to get what I want done.

Ralph Shnelvar

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

Back to top
Richard Smith
Guest





PostPosted: Tue Oct 28, 2003 2:09 am    Post subject: Re: Typedef forward reference Reply with quote


Having just sent a reply to this, I've just realised I
overlooked an important point. In the following code

Quote:
void foo( std::vector<incomplete> const& arg ) {
bar( arg );
}

the name bar is looked up by ADL in the namespace of
incomplete (see last bullet point of 3.4.2/2). As the
std::vector template might declare a friend function called
bar() overloading the one declared here, this has the
potential to change the semantics of the function call, and
thus 14.7.1 allows the implementation to instatiate the
vector. This is what Comeau (correctly) does -- my
apologies for suggesting it was wrong -- I ought to have
known better!

Incidentally, this allows a second way of getting the code
to compile with an incomplete type: qualify the call to bar,
thus disabling ADL. If you change the call to read

::bar( arg );

it will compile again.

Sorry for the confusion.

--
Richard Smith

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

Back to top
Richard Smith
Guest





PostPosted: Tue Oct 28, 2003 2:10 am    Post subject: Re: Typedef forward reference Reply with quote

Siemel Naran wrote:

Quote:
Let's see what the
language experts say about std::vector<IncompleteType>...

The section that talks about instantiating STL components on
incomplete types is 17.4.3.6/1-2:

Quote:
In certain cases [...], the C++ Standard Library depends
on components supplied by a C++ program. If these
components do not meet their requirements, the Standard
places no restriction on the implementation.

In particular, the effects are undefined in the following
cases:

[...]

- if an incomplete type (3.9) is used as a template
argument when instantiating a [STL] template
component.

So, it depends exactly what you do with the vector as to
whether the implementation is allowed to instaniate the
vector. Paragraph 14.7.1/1 says that

Quote:
[...] the class template specialization 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. [...]

So it would initially seem that forwarding an argument by
reference (which does not require a complete type) would
be legal. However, that would be too simple Wink.
Paragraph 14.7.1/4 elaborates on this:

Quote:
[...] in particular, if an expression whose type is a
class template specialization is involved in overload
resolution, pointer conversion, [or] pointer to member
conversion, the class template specialization is
implicitly instantiated [...]

Note the inclusion of overload resolution in this list.
The following paragraph is also of relevance:

Quote:
If the overload resolution process can determine the
correct function to call without instantiating a class
template definition, it is unspecified whether that
instantiation actually takes place.

So the question now seems to be: "is overload resolution
involved?" If so, to be portable the type must be complete.
Clause 13 deals with overloading, and paragraphs 13/1 and
13/2 define the term "overload resolution":

Quote:
When two or more different declarations are specified for
a single name in the same scope, that name is said to be
overloaded. [...]

When an overloaded function name is used in a call, which
overloaded function declaration is being referenced is
determined by [...]. This function selection process is
called overload resolution [...]

Note the requirement for two or more declarations. Thus, I
can see no reason why the following code is allowed to
instantiate std::vector<incomplete>, and I think, therefore,
it is a bug in Comeau online uses.

#include <vector>

class imcomplete;

// Note: bar is not overloaded.
void bar( std::vector<incomplete> const& );

void foo( std::vector<incomplete> const& arg ) {
bar( arg );
}

However, to write more robust code, it would perhaps be
advisable to do something that would prevent overload
resolution possibly happening, and generate a compiler error
(rather than undefined behaviour) if bar happened to be
overloaded. One such possibility would be doing the call
via a function pointer, e.g. replace the line calling bar()
with:

(&bar)(arg);

A good compiler still should be able to inline this call,
but it disables overload resolution. Interestingly, making
this change makes the code compile in Comeau online.

--
Richard Smith

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

Back to top
Gina Yarmel
Guest





PostPosted: Tue Oct 28, 2003 6:41 pm    Post subject: Re: Typedef forward reference Reply with quote

Quote:
Let's see what the
language experts say about std::vector<IncompleteType>...

You can see what one says at:
http://www.cuj.com/documents/s=7986/cujcexp2002austern/

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

Back to top
Hyman Rosen
Guest





PostPosted: Tue Oct 28, 2003 6:43 pm    Post subject: Re: Typedef forward reference Reply with quote

Ralph Shnelvar wrote:
Quote:
somethingUnknown is a complicated type in some header file that I do
_not_ wish to include in the module under consideration.

Too bad. Forward declarations exist so that recursive data types
can be defined (eg., two structures which each contain a pointer
to the other). They are not for avoiding defining types which you
want to use.


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

Back to top
John Potter
Guest





PostPosted: Wed Oct 29, 2003 4:31 pm    Post subject: Re: Typedef forward reference Reply with quote

On 28 Oct 2003 13:41:17 -0500, [email]taintedwheat (AT) yahoo (DOT) com[/email] (Gina Yarmel)
wrote:

Quote:
Let's see what the
language experts say about std::vector<IncompleteType>...

You can see what one says at:
http://www.cuj.com/documents/s=7986/cujcexp2002austern/

That should be "said". The article was contested at the time and
much has happened in the eighteen months since then. He may now
say something other than he said then.

John

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

Back to top
Siemel Naran
Guest





PostPosted: Wed Oct 29, 2003 4:51 pm    Post subject: Re: Typedef forward reference Reply with quote

"Gina Yarmel" <taintedwheat (AT) yahoo (DOT) com> wrote in message

Quote:
You can see what one [expert] says at:
http://www.cuj.com/documents/s=7986/cujcexp2002austern/

Thanks. Awesome article.

Here is a quote

<Quote>
The C++ Standard [8] says that you're not allowed to instantiate a standard
library template with an incomplete type: "the effects are undefined ... if
an incomplete type is used as a template argument when instantiating a
template component." Some implementations do permit it in some
circumstances, but that's just an accident. (Remember, "undefined behavior"
covers absolutely anything - including things working as you might expect
them to!)
</Quote>

Do you think it would be a good idea to relax the rule for std::vector.
IOW, typedef std::vector<IncompleteType> is valid, as in the original post?
After all, we have a special rule that the storage of std::vector must be a
continuous block like a normal C++ array, which means they do sometimes make
special exceptions for this or that container.

--
+++++++++++
Siemel Naran


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

Back to top
Tom Hyer
Guest





PostPosted: Wed Oct 29, 2003 4:52 pm    Post subject: Re: Typedef forward reference Reply with quote

[email]brangdon (AT) cix (DOT) co.uk[/email] (Dave Harris) wrote in message news:<memo.20031027114327.452A (AT) brangdon (DOT) m>...
Quote:

I am surprised. It's hard to see why this:

struct Item;
template <typename T> class Vec;
typedef Vec<Item> ItemVec;

wouldn't be supported. Perhaps the author is thinking of standard
templates? We are not allowed to forward-declare things like
std::vector, but that's because they don't belong to us.

If this is truly not supported, can anyone think of a reason it
shouldn't be added to a future version of the standard?

I would go farther than this -- either we should be allowed to
forward-declare the std classes, or the standard should require
forward-declaring headers (like iosfwd) for each one.

-- Tom Hyer

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

Back to top
Hyman Rosen
Guest





PostPosted: Thu Oct 30, 2003 5:41 am    Post subject: Re: Typedef forward reference Reply with quote

Tom Hyer wrote:
Quote:
I would go farther than this -- either we should be allowed to
forward-declare the std classes, or the standard should require
forward-declaring headers (like iosfwd) for each one.

What in the world for?


[ 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
Goto page 1, 2, 3  Next
Page 1 of 3

 
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.