Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Forward Declarations of types used in template container classes

Reply
Thread Tools

Forward Declarations of types used in template container classes

 
 
Stephen Howe
Guest
Posts: n/a
 
      04-08-2011
Hi

I cant find whether this is valid C++, but I believe it is

// ---------------------------- start header file
#include <vector>

// Forward Declaration
class FooBar;

int SomeFunction1(FooBar); // Valid
declaration, I know this
int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
using std::vector???

// ---------------------------- end header file

Yes FooBar is incomplete but all I am interested in is whether it is a
valid declaration.
All of this is to minimise header file dependency, so FooBar's
definition is not dragged in.
I know that where SomeFunction2 is defined, a full definition of
FooBar is needed.

Thanks

Stephen Howe
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      04-08-2011
On 4/8/2011 5:31 PM, Stephen Howe wrote:
> Hi
>
> I cant find whether this is valid C++, but I believe it is
>
> // ---------------------------- start header file
> #include<vector>
>
> // Forward Declaration
> class FooBar;
>
> int SomeFunction1(FooBar); // Valid
> declaration, I know this
> int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
> using std::vector???
>
> // ---------------------------- end header file
>
> Yes FooBar is incomplete but all I am interested in is whether it is a
> valid declaration.
> All of this is to minimise header file dependency, so FooBar's
> definition is not dragged in.
> I know that where SomeFunction2 is defined, a full definition of
> FooBar is needed.


Since in the context of the declaration of 'SomeFunction2' the full
definition of 'std::vector<FooBar>' is not required, it is not going to
be instantiated. If no instantiation happens, FooBar may be incomplete.
The declaration of 'SomFunction2' is legal, I suppose.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
 
 
 
Noah Roberts
Guest
Posts: n/a
 
      04-08-2011
On 4/8/2011 2:31 PM, Stephen Howe wrote:
> Hi
>
> I cant find whether this is valid C++, but I believe it is
>
> // ---------------------------- start header file
> #include<vector>
>
> // Forward Declaration
> class FooBar;
>
> int SomeFunction1(FooBar); // Valid
> declaration, I know this


You do?

> int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
> using std::vector???


Yes.
--
http://crazycpp.wordpress.com
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      04-09-2011
* Victor Bazarov, on 08.04.2011 23:41:
> On 4/8/2011 5:31 PM, Stephen Howe wrote:
>> Hi
>>
>> I cant find whether this is valid C++, but I believe it is
>>
>> // ---------------------------- start header file
>> #include<vector>
>>
>> // Forward Declaration
>> class FooBar;
>>
>> int SomeFunction1(FooBar); // Valid
>> declaration, I know this
>> int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
>> using std::vector???
>>
>> // ---------------------------- end header file
>>
>> Yes FooBar is incomplete but all I am interested in is whether it is a
>> valid declaration.
>> All of this is to minimise header file dependency, so FooBar's
>> definition is not dragged in.
>> I know that where SomeFunction2 is defined, a full definition of
>> FooBar is needed.

>
> Since in the context of the declaration of 'SomeFunction2' the full definition
> of 'std::vector<FooBar>' is not required, it is not going to be instantiated. If
> no instantiation happens, FooBar may be incomplete. The declaration of
> 'SomFunction2' is legal, I suppose.


Not formally.

C++98 §17.4.3.6/2, about standard library containers:
"In particular, the effects are undefined in the following cases:
[blah blah]
- if an incomplete type (3.9) is used as a template argument when
instantiating a template component"

That is, standard libary containers are special, in that the element type must
(formally) be complete.

A compiler is free to check, by any means, that the type is complete.

Doing such checking yourself might look like this:


<code>
namespace pedantic {

template< class Elem, int enforcedCompleteness = sizeof( Elem ) >
class Vector
{
// ...
};
}

// Forward Declaration
class FooBar;

int SomeFunction1( FooBar ); // Valid.
int SomeFunction2( pedantic::Vector<FooBar>& ref ); // Invalid.

int main()
{}
</code>


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      04-09-2011
Alf P. Steinbach /Usenet wrote:
> * Victor Bazarov, on 08.04.2011 23:41:
>> On 4/8/2011 5:31 PM, Stephen Howe wrote:
>>> Hi
>>>
>>> I cant find whether this is valid C++, but I believe it is
>>>
>>> // ---------------------------- start header file
>>> #include<vector>
>>>
>>> // Forward Declaration
>>> class FooBar;
>>>
>>> int SomeFunction1(FooBar); // Valid
>>> declaration, I know this
>>> int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
>>> using std::vector???
>>>
>>> // ---------------------------- end header file
>>>
>>> Yes FooBar is incomplete but all I am interested in is whether it is a
>>> valid declaration.
>>> All of this is to minimise header file dependency, so FooBar's
>>> definition is not dragged in.
>>> I know that where SomeFunction2 is defined, a full definition of
>>> FooBar is needed.

>>
>> Since in the context of the declaration of 'SomeFunction2' the full
>> definition
>> of 'std::vector<FooBar>' is not required, it is not going to be
>> instantiated. If
>> no instantiation happens, FooBar may be incomplete. The declaration of
>> 'SomFunction2' is legal, I suppose.

>
> Not formally.
>
> C++98 §17.4.3.6/2, about standard library containers:
> "In particular, the effects are undefined in the following cases:
> [blah blah]
> - if an incomplete type (3.9) is used as a template argument when
> instantiating a template component"

Why do you think the declaration in OP has to instantiate std::vector<FooBar>?

From 14.7.1-1 (C++ 2003):
Unless a class template specialization has been explicitly instantiated (14.7.2)
or explicitly specialized
(14.7.3), 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.

std::vector<FooBar>& does not seem to require a completely-defined object.

-Pavel

>
> That is, standard libary containers are special, in that the element
> type must (formally) be complete.
>
> A compiler is free to check, by any means, that the type is complete.
>
> Doing such checking yourself might look like this:
>
>
> <code>
> namespace pedantic {
>
> template< class Elem, int enforcedCompleteness = sizeof( Elem ) >
> class Vector
> {
> // ...
> };
> }
>
> // Forward Declaration
> class FooBar;
>
> int SomeFunction1( FooBar ); // Valid.
> int SomeFunction2( pedantic::Vector<FooBar>& ref ); // Invalid.
>
> int main()
> {}
> </code>
>
>
> Cheers & hth.,
>
> - Alf
>


 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      04-09-2011
* Pavel, on 09.04.2011 05:17:
> Alf P. Steinbach /Usenet wrote:
>> * Victor Bazarov, on 08.04.2011 23:41:
>>> On 4/8/2011 5:31 PM, Stephen Howe wrote:
>>>> Hi
>>>>
>>>> I cant find whether this is valid C++, but I believe it is
>>>>
>>>> // ---------------------------- start header file
>>>> #include<vector>
>>>>
>>>> // Forward Declaration
>>>> class FooBar;
>>>>
>>>> int SomeFunction1(FooBar); // Valid
>>>> declaration, I know this
>>>> int SomeFunction2(std::vector<FooBar>& ref); // But is this, on
>>>> using std::vector???
>>>>
>>>> // ---------------------------- end header file
>>>>
>>>> Yes FooBar is incomplete but all I am interested in is whether it is a
>>>> valid declaration.
>>>> All of this is to minimise header file dependency, so FooBar's
>>>> definition is not dragged in.
>>>> I know that where SomeFunction2 is defined, a full definition of
>>>> FooBar is needed.
>>>
>>> Since in the context of the declaration of 'SomeFunction2' the full
>>> definition
>>> of 'std::vector<FooBar>' is not required, it is not going to be
>>> instantiated. If
>>> no instantiation happens, FooBar may be incomplete. The declaration of
>>> 'SomFunction2' is legal, I suppose.

>>
>> Not formally.
>>
>> C++98 §17.4.3.6/2, about standard library containers:
>> "In particular, the effects are undefined in the following cases:
>> [blah blah]
>> - if an incomplete type (3.9) is used as a template argument when
>> instantiating a template component"
>>
>> That is, standard libary containers are special, in that the element
>> type must (formally) be complete.
>>
>> A compiler is free to check, by any means, that the type is complete.
>>
>> Doing such checking yourself might look like this:
>>
>>
>> <code>
>> namespace pedantic {
>>
>> template< class Elem, int enforcedCompleteness = sizeof( Elem ) >
>> class Vector
>> {
>> // ...
>> };
>> }
>>
>> // Forward Declaration
>> class FooBar;
>>
>> int SomeFunction1( FooBar ); // Valid.
>> int SomeFunction2( pedantic::Vector<FooBar>& ref ); // Invalid.
>>
>> int main()
>> {}
>> </code>


> Why do you think the declaration in OP has to instantiate std::vector<FooBar>?
>
> From 14.7.1-1 (C++ 2003):
> Unless a class template specialization has been explicitly instantiated (14.7.2)
> or explicitly specialized
> (14.7.3), 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.
>
> std::vector<FooBar>& does not seem to require a completely-defined object.


Uh, you're right, it's not instantiated here. Sorry for noize.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Stephen Howe
Guest
Posts: n/a
 
      04-09-2011
> * * *C++98 17.4.3.6/2, about standard library containers:
> * * *"In particular, the effects are undefined in the following cases:
> * * * [blah blah]
> * * * - if an incomplete type (3.9) is used as a template argument when
> * * * * instantiating a template component"


Yes but Alf I am only interested in legality of declaration, not
definition (nor instantiation).
I can assure you that at the point when I call the function, the full
definition of FooBar will be available.

I am trying to minimise the amount of header file inclusion by forward
declaring items as much as possible.
I know that it perfectly legal for non-template class/struct/union
parameters (but interestingly enum is left out (any aficionado saying
that size matters here is wrong, if it does not matter for class/
struct/union, it should not matter for enum; enum has been
overlooked)).
I was just discussing the legality of template container parameters
where the containing type is incomplete, and as others have concluded,
it is legal.

That just leaves std::string and similar where unfortunately you do
have to do have to do #include <string>, you cannot forward declare.
And I do know about header file <iosfwd> which is useful to know (wish
other std:bject types had a fwd header).

Thanks

Stephen Howe





 
Reply With Quote
 
Stephen Howe
Guest
Posts: n/a
 
      04-09-2011
Pavel

If I had

int SomeFunction3(std::vector<FooBar> ref);

in a declaration, I dont think this requires FooBar to be complete
either.

For a long time, I thought only references and pointer types can be
incomplete.
But I read Scott Meyers and he assured return-by-value and pass-by-
value types can also be incomplete (as long as it just a declaration).
This seems right.
I went through another round of removing headers and replacing with
forward declarations.

I think the template containers with incomplete types have exactly the
same semantics as struct/class/union parameters that are incomplete.

This is great news - miminise header file dependency, increase
compilation speed (less headers for the compiler to wade through). If
I do "#include myheader.h", I really want to minimise the number of
dependent headers that are sub-included.

All that really matters is when you come to call the function or
define it, you do have full set of definitions then.

Thanks

Stephen Howe

 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      04-10-2011
Stephen Howe wrote:
> Pavel
>
> If I had
>
> int SomeFunction3(std::vector<FooBar> ref);
>
> in a declaration, I dont think this requires FooBar to be complete
> either.
>
> For a long time, I thought only references and pointer types can be
> incomplete.
> But I read Scott Meyers and he assured return-by-value and pass-by-
> value types can also be incomplete (as long as it just a declaration).
> This seems right.
> I went through another round of removing headers and replacing with
> forward declarations.
>
> I think the template containers with incomplete types have exactly the
> same semantics as struct/class/union parameters that are incomplete.
>
> This is great news - miminise header file dependency, increase
> compilation speed (less headers for the compiler to wade through). If
> I do "#include myheader.h", I really want to minimise the number of
> dependent headers that are sub-included.
>
> All that really matters is when you come to call the function or
> define it, you do have full set of definitions then.
>
> Thanks
>
> Stephen Howe
>

Thanks Stephen!

This is a nice feature to slash some compilation time, especially for headers
with fat APIs where complete types of many parameters are not needed till the
end of the including translation unit. It's somewhat less of a saver for highly
coherent APIs.

-Pavel
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Nested classes, forward declarations. jason.cipriani@gmail.com C++ 2 12-23-2008 07:52 AM
forward declarations and incomplete types fmassei@gmail.com C Programming 7 07-19-2008 08:39 PM
template template par used for a container statistic er C++ 1 09-05-2007 07:07 AM
types of classes in template classes lobequadrat@googlemail.com C++ 5 04-27-2007 05:33 PM
Re-forward declaration of types which were already forward declared qazmlp C++ 1 02-15-2004 07:00 PM



Advertisments