Some stuff about C++ and development

Preview:

DESCRIPTION

A talk I first gave at Amadeus in Nice, 18th April 2013. Includes the #include test.

Citation preview

some stuff about C++ and development

sequence points

5.1.2.3 Program execution. Clause 2

At certain specified points in the execution sequence called

sequence points, all side effects of previous evaluations shall be

complete and no side effects of subsequent evaluation shall have

taken place.

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

Most C and C++ programmers use an implicit mental model made up of lots of sequence points,

progressing in a mostly left-to-right order.

i + v[++i] + v[++i]

sequence points

In reality C and C++ have very few sequence points(this is to give maximum scope for optimization).

sequence points where?

• at the end of a full expression

• after the first operand of these operators && || ?: ,

• after evaluation of all arguments and the function call expression in a function call

only sequence points

govern the order of evaluation

got it?

sequence points

i = v[++i] + v[++i];

question: where are the sequence points in this statement ?

sequence points

i = v[++i] + v[++i];

answer: here!

why does this matter?

I'm glad you asked!

here's why...

shall

If a "shall" or a "shall not" requirement that appears outside of a constraint is

violated, the behavior is undefined.

4. Conformance. Clause 2

undefined behavior: behavior ... for which this International Standard imposes no requirements.

3. Terms, definitions, and symbols

sequence point: rule-one

Between the previous and next sequence point an object shall have its stored value modified at most once by

the evaluation of an expression.

n = n++;

6.5 Expressions. Clause 2.

undefined behavior

sequence point: rule-one

Between the previous and next sequence point an object shall have its stored value modified at most once by

the evaluation of an expression.

n = n++;

6.5 Expressions. Clause 2.

undefined behavior

sequence point: rule-two

Between the previous and next sequence point the prior value shall be read only to determine the value to be

stored.

n + n++;

6.5 Expressions. Clause 2.

undefined behavior

sequence point: rule-two

Between the previous and next sequence point the prior value shall be read only to determine the value to be

stored.

n + n++;

6.5 Expressions. Clause 2.

undefined behavior

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

(Mac OS 10.8.2)

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

(Mac OS 10.8.2)

$ gcc foo.c && ./a.out12

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

$ clang foo.c && ./a.out

clang

(Mac OS 10.8.2)

$ gcc foo.c && ./a.out12

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

$ clang foo.c && ./a.out

clang

(Mac OS 10.8.2)

$ gcc foo.c && ./a.out12

$ clang foo.c && ./a.out11

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

$ clang foo.c && ./a.out

clang

$ icc foo.c && ./a.out

icc

(Mac OS 10.8.2)

$ gcc foo.c && ./a.out12

$ clang foo.c && ./a.out11

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>

int main(void){ int v[] = { 0,2,4,6,8 }; int i = 1; int n = i + v[++i] + v[++i]; printf("%d\n", n);}

$ gcc foo.c && ./a.out

gcc

$ clang foo.c && ./a.out

clang

$ icc foo.c && ./a.out

icc

(Mac OS 10.8.2)

$ gcc foo.c && ./a.out12

$ clang foo.c && ./a.out11

$ icc foo.c && ./a.out13

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    dst[i] = src[i++];    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

$ gcc *.c && ./a.out

gcc 4.8.0 20130210

example

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    dst[i] = src[i++];    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

$ gcc *.c && ./a.out$ gcc *.c && ./a.out0 2 0 0

gcc 4.8.0 20130210

example

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    dst[i] = src[i++];    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

$ gcc *.c && ./a.out$ gcc *.c && ./a.out0 2 0 0

gcc 4.8.0 20130210

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    *(dst + i) = *(src + i++);    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

example

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    dst[i] = src[i++];    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

$ gcc *.c && ./a.out $ gcc *.c && ./a.out$ gcc *.c && ./a.out0 2 0 0

gcc 4.8.0 20130210

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    *(dst + i) = *(src + i++);    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

example

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    dst[i] = src[i++];    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

$ gcc *.c && ./a.out $ gcc *.c && ./a.out$ gcc *.c && ./a.out0 2 0 0

$ gcc *.c && ./a.out0 0 2 0

gcc 4.8.0 20130210

#include <stdio.h>

int main(void) {    int src[] = { 1,2,3,4 };    int dst[] = { 0,0,0,0 };    int i = 1;    *(dst + i) = *(src + i++);    printf("%d %d %d %d\n", dst[0], dst[1], dst[2], dst[3]);}

precedence is not the same as order of

evaluation

order of evaluation is mostly unspecified

and is a run-time thing

precedence iscompletely specified

and is a compile-time thing

precedence determines which operands

bind to which operators

a * b + c

example

a * b + c?

a * b + c?

a() * b() + c()

temp_a = a();temp_b = b();temp_c = c();a * b + c

temp_c = c();temp_b = b();temp_a = a();a * b + c

temp_b = b();temp_c = c();temp_a = a();a * b + c

example#include <iostream>...int main(){ int sum = a() + b(); std::cout << sum;}

#include <iostream>...int a(){ std::cout << "a"; return 3;}

#include <iostream>...int b(){ std::cout << "b"; return 4;}

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <iostream>...int main(){ int sum = a() + b(); std::cout << sum;}

$ g++ *.c && ./a.out

#include <iostream>...int a(){ std::cout << "a"; return 3;}

#include <iostream>...int b(){ std::cout << "b"; return 4;}

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <iostream>...int main(){ int sum = a() + b(); std::cout << sum;}

$ g++ *.c && ./a.out

#include <iostream>...int a(){ std::cout << "a"; return 3;}

#include <iostream>...int b(){ std::cout << "b"; return 4;}

$ g++ *.c && ./a.outab7

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <iostream>...int main(){ int sum = a() + b(); std::cout << sum;}

$ g++ *.c && ./a.out $ g++ *.c && ./a.out

#include <iostream>...int a(){ std::cout << "a"; return 3;}

#include <iostream>...int b(){ std::cout << "b"; return 4;}

$ g++ *.c && ./a.outab7

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <iostream>...int main(){ int sum = a() + b(); std::cout << sum;}

$ g++ *.c && ./a.out $ g++ *.c && ./a.out

#include <iostream>...int a(){ std::cout << "a"; return 3;}

#include <iostream>...int b(){ std::cout << "b"; return 4;}

$ g++ *.c && ./a.outab7

$ g++ *.c && ./a.outba7

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

indeterminate value

6.2.4 Storage duration of objects

The initial value of the object is indeterminate.

J.2 Undefined behavior

The value of an object with automatic storage duration is used while it is indeterminate.

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc

Without optimization...

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc

Without optimization...

true

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang

Without optimization...

true

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang

Without optimization...

true false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

true false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

true false truefalse

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

false false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

false false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

example#include <stdio.h>#include <stdbool.h>

void bar(void){ bool b; if (b) printf("true\n"); if (!b) printf("false\n");}

void foo(void);void bar(void);

int main(void){ foo(); bar();}

void foo(void){ char c = 2; ...}

gcc clang icc

Without optimization...

With optimization...

true false truefalse

false false false

http://www.pvv.org/~oma/UnspecifiedAndUndefined_ACCU_Apr2013.pdf

why do cars have brakes?

so you can drive faster!

do you do unit testing?

what do you mean by the word

unit ?

it's nothing to do with size

A

tests

A

tests

B

A

tests

C

B

A

tests

C

B

D

A

tests

C

B

D

E

A

tests

C

B

F

D

E

A

tests

C

B

FG

D

E

A

tests

C

B

FG

D

E

extern

al boundary

A

tests

C

B

FG

D

database

extern

al boundary

A

tests

C

B

Fregistry

D

database

extern

al boundary

A

tests

C

B

Fregistry

D

file system

extern

al boundary

A

tests

C

B

Fsocket

D

file system

extern

al boundary

A

tests

C

B

F

socket

D

file system

extern

al boundary

unit tests should pass or fail based solely on the correctness of our tests

and our code

A

tests

C

B

F

socket

D

file system

extern

al boundary

not based on the correctness of external code and its environment

this means we have to design "seams"

into our architecture

A

tests

C

B

F

socket

D

file system

substitutefile system

substitutesocket

seam

seam

this is a useful

definition

it means unit tests

are...

so fast, your basic development

activity can change from...

re-compiling

to...

re-running the unit tests

this is not a mere quantitative

change

it is a qualitative change

some more about tests being...

void example_of_use(){ q = snafu::instance().query(...) ... snafu::instance().modifier(...); ...}

spot the anti-pattern

class snafu {public: // singleton static snafu & instance(); public: // api int query(...) const; void modifier(...);

private: // inappropriate snafu(const snafu &); snafu & operator=(const snafu &); private: // 'tors snafu(); ~snafu(); };

singleton

this is the only good singleton

A

tests

C

B

F

socket

D

file system

substitutefile system

substitutesocket

seam

seam

1

singleton

A

unittest

C

B

F

D

1

danger

A

unittest

C

B

F

D

1

anotherunittest

danger

you should be able to run your

unit tests in any order

you should be able to run your

unit tests in parallel

unit tests

integration

system

no externaldependencies

some externaldependencies

all externaldependencies

waterfall

anal

ysis

desi

gn

impl

emen

t

test

waterfall

anal

ysis

desi

gn

impl

emen

t

debu

g

Debugging is twice as hard as writing the code in the first

place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart

enough to debug it.

"agile"... ... ...test ... ... ...test ... ... ...test

virtual destructor?

class dice_roller{public: virtual ~dice_roller(); ... virtual int roll_dice() const = 0;};

question:what does a virtual destructor mean?

virtual destructor

class random_dice_roller : public dice_roller{public: ...};

answer:any code can delete a derived object through a base class pointers*

void contrived_example(){ dice_roller * ptr = new random_dice_roller(); ... delete ptr;}

* and it will work!

virtual destructor

class random_dice_roller : public dice_roller{public: ...};

answer:any code can delete a derived object through a base class pointers*

void contrived_example(){ dice_roller * ptr = new random_dice_roller(); ... delete ptr;}

* and it will work!

virtual destructor?

class random_dice_roller : public dice_roller{public: ...};

question:should any code be able to write delete expressions?

void contrived_example(){ dice_roller * ptr = new random_dice_roller(); ... delete ptr;}

class dice_roller{public: virtual ~dice_roller(); ...};

virtual destructor

suppose you don't want arbitrary code to be able to write delete expressions?

void contrived_example(){ dice_roller * ptr = new random_dice_roller(); ... delete ptr;}

class dice_roller{public: ...protected: ~dice_roller();};

bad inheritance

alpha

beta

gamma

delta

new alpha()

new beta()

new gamma()

new delta()

good inheritance

alpha beta gamma

abstraction

delta

client

factory pattern

abstractfactory

abstractproduct

concreteproduct

concretefactory

<<creates>>

<<creates>>

client

#include header

#include "wibble.hpp"

class fubar {

};

inheritance

#include "wibble.hpp"

class fubar : public wibble // 1{

};

member function parameters

#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

};

member function return types

#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

};

data members

#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

};

static data member#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11 static wibble & shared_ref; // 12 static wibble * shared_ptr; // 13};

forward declarationclass wibble;

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11 static wibble & shared_ref; // 12 static wibble * shared_ptr; // 13};

which of 1..13 require #include ?#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11 static wibble & shared_ref; // 12 static wibble * shared_ptr; // 13};

my assistant will now collect up the

answers

the answer is...

class wibble;

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11 static wibble & shared_ptr; // 12 static wibble * shared_ptr; // 13};

we'll see how you all did shortly!

#include in .hpp .cpp

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"#include "snafu.hpp"#include "widget.hpp"

class fubar { ...};

#endif

#include "fubar.hpp"

...

fubar.hpp client.cpp

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class snafu;class widget;

class fubar { ...};

#endif

#include "fubar.hpp"#include "snafu.hpp"#include "widget.hpp"

...

fubar.hpp client.cpp

• compile times down• physical coupling down• happiness up

#include in .hpp .cpp

how much does a #include cost?

#include <string>

includer.cpp

$ g++ -H includer.cpp &> lines$ wc -l lines

how much does a #include cost?

#include <string>

includer.cpp

$ g++ -H includer.cpp &> lines$ wc -l lines

. /usr/include/c++/4.2.1/string

.. /usr/include/c++/4.2.1/bits/c++config.h

... /usr/include/c++/4.2.1/bits/os_defines.h

.... /usr/include/unistd.h

..... /usr/include/_types.h

...... /usr/include/sys/_types.h

....... /usr/include/sys/cdefs.h

........ /usr/include/sys/_symbol_aliasing.h

........ /usr/include/sys/_posix_availability.h

....... /usr/include/machine/_types.h

........ /usr/include/i386/_types.h

..... /usr/include/sys/unistd.h

...... /usr/include/sys/cdefs.h ... ... ...... /usr/include/c++/4.2.1/bits/stl_uninitialized.h... /usr/include/c++/4.2.1/bits/stl_algo.h.... /usr/include/c++/4.2.1/bits/stl_heap.h..... /usr/include/c++/4.2.1/debug/debug.h.... /usr/include/c++/4.2.1/bits/stl_tempbuf.h..... /usr/include/c++/4.2.1/memory.... /usr/include/c++/4.2.1/debug/debug.h.. /usr/include/c++/4.2.1/bits/basic_string.tcc

how much does a #include cost?

#include <string>

includer.cpp

$ g++ -H includer.cpp &> lines$ wc -l lines

. /usr/include/c++/4.2.1/string

.. /usr/include/c++/4.2.1/bits/c++config.h

... /usr/include/c++/4.2.1/bits/os_defines.h

.... /usr/include/unistd.h

..... /usr/include/_types.h

...... /usr/include/sys/_types.h

....... /usr/include/sys/cdefs.h

........ /usr/include/sys/_symbol_aliasing.h

........ /usr/include/sys/_posix_availability.h

....... /usr/include/machine/_types.h

........ /usr/include/i386/_types.h

..... /usr/include/sys/unistd.h

...... /usr/include/sys/cdefs.h ... ... ...... /usr/include/c++/4.2.1/bits/stl_uninitialized.h... /usr/include/c++/4.2.1/bits/stl_algo.h.... /usr/include/c++/4.2.1/bits/stl_heap.h..... /usr/include/c++/4.2.1/debug/debug.h.... /usr/include/c++/4.2.1/bits/stl_tempbuf.h..... /usr/include/c++/4.2.1/memory.... /usr/include/c++/4.2.1/debug/debug.h.. /usr/include/c++/4.2.1/bits/basic_string.tcc

$ g++ -H includer.cpp &> lines$ wc -l lines 244 lines

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class snafu;class widget;

class fubar { ...};

#endif

namespace fishing{ class snafu { ... };}

fubar.hppfishing/snafu.hpp

namespace fishing{ class widget { ... };}

fishing/widget.hpp

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

namespace fishing{ class snafu; class widget;}

class fubar { ...};

#endif

fubar.hppnamespace fishing{ class snafu { ... };}

fishing/snafu.hpp

namespace fishing{ class widget { ... };}

fishing/widget.hpp

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

namespace std{ class string;}

class fubar { ...};

#endif

namespace std{ class string { ... };}

fubar.hpp <string>

it's not like this!

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

namespace std{ class string;}

class fubar { ...};

#endif

namespace std{ template<typename T> class basic_string { ... };

typedef basic_string<char> string; ...

}

fubar.hpp <string>

it's a bit like this!

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

namespace std{ template<typename T> class basic_string;

typdef basic_string<char> string;}

class fubar { ...};

#endif

namespace std{ template<typename T> class basic_string { ... };

typedef basic_string<char> string; ...

}

fubar.hpp <string>

??

you must not tell lies!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

namespace std{ template<typename T> class basic_string;

typdef basic_string<char> string;}

class fubar{ ...};

#endif

namespace std{ template<typename T1, typename T2 = ..., typename T3 = ...> class basic_string { ... };

typedef basic_string<char> string; ...

}

fubar.hpp <string>default template types

don't forward declare anything in std::

template

#ifndef SNAFU_INCLUDED#define SNAFU_INCLUDED

#include <algorithm>...

template<typename T>class snafu{public: void reserve(int limit) { std::for_each(...) } ...};

#endif

snafu.hpp

templates canincreasecoupling

template

#ifndef SNAFU_INCLUDED#define SNAFU_INCLUDED

...

template<typename T>class snafu{public: void reserve(int limit); ...};

#include "snafu-template.hpp"

#endif

#include <algorithm>

template<typename T>void snafu<T>::reserve(int limit){ std::for_each(...)}

...

snafu.hpp snafu-template.hpp

templates canincreasecoupling

inline

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include <vector>

class fubar{public: typedef std::vector<int>::iterator iterator;

void algo(iterator from, iterator to) { ... } ...};

inlining usually increases coupling

fubar.hpp

template

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

...

class fubar{public: template<typename iterator> void algo(iterator from, iterator to) { ... } ...};

#endif

#include "fubar.hpp"#include <vector>

void eg(std::vector<int> & v){ fubar f; f.algo(v.begin(), v.end());}

fubar.hppexample.cpp

templates canalso decrease

coupling!

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include <vector>#include "fubar.hpp"

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include <vector>#include "fubar.hpp"

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

yes

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"#include <vector>

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"#include <vector>

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

no

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"#include <vector>

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"#include <vector>

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"...

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

does this compile?

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"#include <vector>

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"...

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

yes

include your own header 1st

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"#include <vector>

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

#include "fubar.hpp"...

void fubar::fu(){ ...}

fubar.hpp fubar.cpp

better still - make sure each header compiles (on its own) as

part of the build!

#ifndef FUBAR_INCLUDED#define FUBAR_INCLUDED

#include "wibble.hpp"#include <vector>

class fubar{public: ... void fu(); ...private: std::vector<wibble> wibbles;};

#endif

fubar.hpp

remember this...

#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11};

the answer is...

#include "wibble.hpp"

class fubar : public wibble // 1{ void value_parameter(wibble ); // 2 void ref_parameter(wibble &); // 3 void ptr_parameter(wibble *); // 4

wibble value_result(); // 5 wibble & ref_result(); // 6 wibble * ptr_result(); // 7

wibble value; // 8 wibble & ref; // 9 wibble * ptr; // 10

static wibble shared_value; // 11};

how did you all do?

over to my assistant...

the Satir change curve

old status quo

new status quo old status quo

foreign element

resistance and chaosin

tegr

atio

n an

d pr

acti

cetime

com

pete

nce

@JonJaggerjon@jaggersoft.com