Boost logo

Boost :

From: scleary_at_[hidden]
Date: 2000-06-30 15:51:25


> One idea was to have a specialization of the compressed_pair's
> implementation class that is just plain missing the empty class object
> (instead of inheriting from it). The problem with this is that if the
> empty class does something in its constructor/destructor, then that
> something will not happen as it should.

Well, I haven't tried it, but you could try something totally crazy, like
faking a "this" pointer:

// (this code assumes that the empty type is the first() element of
// the compressed_pair, but that shouldn't be too hard to change)

template <typename empty_type, typename non_empty_type>
class gcc_compressed_pair
{
  private:
    non_empty_type m;

    empty_type * fake_this()
    { return reinterpret_cast<empty_type *>(this); }
    const empty_type * fake_this() const
    { return reinterpret_cast<const empty_type *>(this); }

  public:
    gcc_compressed_pair()
    {
      // Explicitly call default constructor
      new (fake_this()) empty_type();
    }
    explicit gcc_compressed_pair(const non_empty_type & nm)
    :m(nm)
    {
      // Explicitly call default constructor
      new (fake_this()) empty_type();
    }
    explicit gcc_compressed_pair(const empty_type & n)
    {
      // Explicitly call copy constructor
      new (fake_this()) empty_type(n);
    }
    gcc_compressed_pair(const empty_type & n,
        const non_empty_type & nm)
    :m(nm)
    {
      // Explicitly call copy constructor
      new (fake_this()) empty_type(n);
    }
    gcc_compressed_pair(const gcc_compressed_pair & other)
    :m(other.m)
    {
      // Explicitly call copy constructor
      new (fake_this()) empty_type(other.first());
    }

    gcc_compressed_pair & operator=(
        const gcc_compressed_pair & other)
    {
      m = other.m;
      // Explicitly call assignment operator
      first() = other.first();
    }

    ~gcc_compressed_pair()
    {
      // Explicitly call destructor
      fake_this()->~empty_type();
    }

    empty_type & first() { return *fake_this(); }
    const empty_type & first() const { return *fake_this(); }
    non_empty_type & second() { return m; }
    const non_empty_type & second() const { return m; }
};

There are two Standard problems with the above solution AFAIK:
  1) The binding of the reference for first() is illegal [8.3.2/4] [8.5.3/1]
because a reference *must* refer to a "valid object" (presumably one of the
referred-to type).
  2) The reinterpret_cast in fake_this() has unspecified behaviour
[5.2.10/7].

However, I don't think these would cause a problem on most compilers; this
code *is* going to be specific to certain compilers, so maybe you can take a
few liberties.

Just a thought. :)

        -Steve


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk