Question about Item 23 of C++ coding standard

S

sharpblade

The title of these Item is "Make header files self-sufficient"
There're two examples in this Item:

Example 1: Dependent names. Templates are compiled at the point where
they are defined, except that any dependent names or types are not
compiled until the point where the template is instantiated. This means
that a template<class T> class Widget with a std::deque<T> member does
not incur a compile-time error even when <deque> is not included, as
long as nobody instantiates Widget. Given that Widget exists in order
to be instantiated, its header clearly should #include <deque>.

Example 2: Member function templates, and member functions of
templates, are instantiated only if used. Suppose that Widget doesn't
have a member of type std::deque<T>, but Widget's transmogrify member
function uses a deque. Then Widget's callers can instantiate and use
Widget just fine even if no one includes <deque>, as long as they don't
use TRansmogrify. By default, the Widget header should still #include
<deque> because it is necessary for at least some callers of Widget. In
rare cases where an expensive header is being included for few rarely
used functions of a template, consider refactoring those functions as
nonmembers supplied in a separate header that does include the
expensive one.

I wrote examples according it:

*********example1:
//widget.h
#include <iostream>
#include <deque> //without this, complie error
generated.

template<typename T> class Widget {
std::deque<T> foo_;
int type_;
public:
void printWidget() {std::cout << "Widget\n";}
};

//widget.c
#include "widget.h"

int main(void) {
return 0;
}

*********example2:

//widget.h
#include <iostream>
#include <deque>
#include <vector> //without this, complie error generated.

template<typename T> class Widget {
std::deque<T> foo_;
int type_;
public:
void printWidget() {std::cout << "Widget\n";}
void useVector() {std::vector<T> v;}
};

//widget.c
#include "widget.h"

int main(void) {
Widget<int> wgt;
wgt.printWidget();
return 0;
}

I compile it using g++ under Linux. Why the result is different with
what the book says?
Can anyone give some advice?
 
V

Victor Bazarov

sharpblade said:
[...]
I compile it using g++ under Linux. Why the result is different with
what the book says?

I just tried your code with gcc 4.1.0-3, and no error was generated.
Can anyone give some advice?

Upgrade your compiler.

V
 
P

Phlip

sharpblade said:
The title of these Item is "Make header files self-sufficient"

Did they point out the best technique to make that super easy? Given a
module (group of classes) called Foo, declare them in Foo.h, and define them
in Foo.cpp.

The first line of Foo.cpp is this:

#include "Foo.h"

Because there's nothing above the #include line, Foo.h must be capable of
compiling all its declarations. The best way uses forward declarations, like
this:

class Bar;

class Foo
{
...
Bar & aBar;
};

The next best way nests more #include files inside Foo.h. But sometimes we
must do that.
There're two examples in this Item:

Example 1: Dependent names. Templates are compiled at the point where
they are defined, except that any dependent names or types are not
compiled until the point where the template is instantiated. This means
that a template<class T> class Widget with a std::deque<T> member does
not incur a compile-time error even when <deque> is not included, as
long as nobody instantiates Widget. Given that Widget exists in order
to be instantiated, its header clearly should #include <deque>.

Without #include <deque> inside Foo.h, can my Foo.cpp start with this?

#include "Foo.h"
#include <deque>

If it can, then it breaks my guideline that we can detect Foo.h's
Example 2: Member function templates, and member functions of
templates, are instantiated only if used. Suppose that Widget doesn't
have a member of type std::deque<T>, but Widget's transmogrify member
function uses a deque. Then Widget's callers can instantiate and use
Widget just fine even if no one includes <deque>, as long as they don't
use TRansmogrify. By default, the Widget header should still #include
<deque> because it is necessary for at least some callers of Widget. In
rare cases where an expensive header is being included for few rarely
used functions of a template, consider refactoring those functions as
nonmembers supplied in a separate header that does include the
expensive one.

Again said:
void printWidget() {std::cout << "Widget\n";}
void useVector() {std::vector<T> v;}

These are member functions, not member function templates. Make them
templates, based on either T or something else, and see what happens.
I compile it using g++ under Linux. Why the result is different with
what the book says?

Because the authors spend too much time reading the Standard. ;-)

No compiler exactly matches the Standard. So note that Herb & Alex's advice
devolves to what we must do with less-than-Standard compilers. #include
<deque> inside our widget.h. If <deque> were instead something heavy,
refactor _everything_ to put the deque into a delegated object.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top