//
// Pimpl
//

// file x.h
class X
{
public:
    // public members
protected:
    // protected members
private:
    // pointer to forward declared class
    class XImpl *pimpl_;  // opaque pointer
};


Questions: -- What should go into XImpl? Options are:

-- Put all private data but not functions into XImpl.
   Not too bad, but there is better

-- Put all private members into XImpl.

-- Put all private and protected members into XImpl.
   Bad, protected members must be in X

-- Make XImpl entirely the class that X would have been, and write X as
   only the public interface made up entirely of simple forwarding functions
   handle body variant.

-- Does XImpl require a pointer back to the X object?

Caveats:

-- You can't hide virtual member functions in the Pimpl (here private
   inheritance differs from membership)

-- Functions in Pimpl may require a "back pointer" to the visible object
   (by convention that is called: self_.

-- Often the best compromise is to use Option 2, and in addition to put
   into XImpl only rhose non-private functions that need to be called by
   private ones.

-- 4th is better over 2nd not needed "back pointer", but X is useless
   for inheritance.


// file: y.h

class Y
{
    //...
    static const size_t sizeofx = /* ... */;
    char x_[sizeofx];
};


// file: y.cpp

#include "x.h"

Y::Y()
{
    assert( sizeofx >= sizeof(X) );
    new(&x_[0]) X;
}

Y::~Y()
{
    (reinterpret_cast<X*>(&x_[0]))->~X();
}



//
// Template codeblow
//

template <class T>
class matrix
{
public:
    // ...
private:
    // ...
};


// 
// separate type parameter independent parts
//

class matrixBase
{
public:
    // ...
protected:
    // ...
};

template <class T>
class matrix : public matrixBase
{
    // ...
};



//
// Using C and C++ together
//

// this is a c source, compile with gcc

struct Y
{
    int y_;
};

int cfunc( double x, struct Y y, double z)
{
    return  y.y_;
}

//
// this is a cpp source, compile with g++
//
#include <iostream>

using namespace std;

struct Y
{
    int y_;
    virtual void f() {};    // this makes the problem!
};

extern "C" int cfunc( double x, struct Y y, double z);

int main()
{
    Y y;
    y.y_ = 1;
    cout << cfunc(3.14, y, 4.14) << endl;   // bad!

    return 0;
}


//
// Using C libraries from C++
//


// C++ header for C files:
extern "C"
{
    int     f(int);
    double  g(double, int);
    // ...
}

// C++ header for C/C++ files:
#ifdef __cplusplus
extern "C"
{
#endif
    int     f(int);
    double  g(double, int);
    // ...
#ifdef __cplusplus
}
#endif



//
// Order of linking
//

// file: t.h
template <class T>
T t(const T&)
{
    return s;
}

// file: a.cpp
#include "t.h"
static int s = 2;

int g()
{
    return t(1);
}

// file: b.cpp
#include "t.h"
static int s = 1;

int h()
{
    return t(1);
}

// file: main.cpp
#include <iostream>

extern int g();
extern int h();

int main()
{
    std::cout << g() << std::endl;
    std::cout << h() << std::endl;
    return 0;
}

// g++ main.cpp a.cpp b.cpp
// 2 2

// g++ main.cpp b.cpp a.cpp
// 1 1