This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Function References and Unions
  Submitted by



1. Function references.

Many C++ programmers know about function pointers. But far fewer know that there are function references in C++ as well. However, because they are references, they lack the ability to be reassigned, so their usefulness can be questionable at times. After all, one of the most important reasons to use function pointers is this reassignability, right?

Their syntax however, is similar to that of function pointers:

int f(int);

int (*pointer1)(int) = &f; // Address-of not strictly necessary int (*pointer2)(int) = f; int (&reference)(int) = f;

(*pointer1)(5); // Dereferencing not strictly necessary pointer2(5); reference(5);



2. Some things you never knew about unions. (Unless you read "9.5 Unions" in the C++ standard that is. ;)

C unions are also a widely known phenomenon. They allow multiple objects to occupy the same memory space. In C++, unions fulfill the same role, but can do much more. A union in C++ is in fact very much like a class. Here are some things that a union can and can't do according to the C++ standard:

  • A union can have member functions (including constructors and destructors), but not virtual functions.
  • A union shall not have base classes.
  • A union shall not be used as a base class.

  • An anonymous union shall not have function members.
  • An anonymous union shall not have private or protected members.


  • (Note: a union hasn't got much use for protected members anyway. It can't be used as a base class. ;)

    For those who don't know what an anonymous union is, here's a little example:

    union { int a1; float b1; };           // Anonymous union
    union { int a2; float b2; } object1;   // Not an anonymous union
    union SomeUnion { int a3; float b3; }; // Not an anonymous union either
    SomeUnion object2;

    a1 = 5; // Legal a2 = 5; // Illegal object1.a2 = 5; // Legal a3 = 5; // Illegal object2.a3 = 5; // Legal



    According to the previous rules (and MSVC6 SP5) the following code is perfectly legal:

    #include <cassert

    template< class T union Vector3D { // Public access to x,y,z components struct { T x, y, z; }; private: T v3[3];

    // Check for proper alignment bool AlignmentCheck() { return (&v3[0] == &x) && (&v3[1] == &y) && (&v3[2] == &z); }

    public: // Constructors Vector3D() // Fast but potentially dangerous: no initialization { assert(AlignmentCheck()); } Vector3D(T x_, T y_, T z_) : x(x_), y(y_), z(z_) { assert(AlignmentCheck()); }

    // Accessors T& operator[](unsigned int index) { assert(index < 3); return v3[index]; } T operator[](unsigned int index) const { assert(index < 3); return v3[index]; }

    // ... };

    I placed the alignment check in there because I'm not 100% sure if v3 and x,y,z are guaranteed to be identically aligned for all types. In my test code (using float, double and int) it worked like a charm though.

    See also: The International C++ Standard (ISO/IEC 14882-1998). Available in PDF for US $18 from ANSI.




    The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

     

    Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
    Please read our Terms, Conditions, and Privacy information.