I'm working my way through Eckel's "Thinking in C++ " book at the moment and if I interpreted it correctly, the following code should be incorrect (compiler-warning for the "void g(X ex);"):

Code:
struct X;

struct Y {
  void f(X*);
  void g(X ex);
};


struct X { // Definition
private:
  int i;
public:
  friend void Y::f(X*); 
  friend void Y::g(X);
  void initialize();
 };


void Y::g(X ex) {
  ex.i = 3333;
}
But at least the GCC compiler can work with this. According to the book, the Y::g declaration is supposed to fail because the compiler needs to know "the entire structure definition of X, to know the size and how to pass it", whereas Y::f only takes the address of an X object and the compiler can handle this without the definition of X.
My question is if the code above is valid (would work on other compilers as well) or if it's just GCC that can handle this.