1

I have a C struct from a third-party library that I do not control, and I'd like to extend it with some non-virtual methods by wrapping it in a C++ class. For example:

struct Base
{
    int x;
};

class Wrapper : public Base
{
public:
    int square() const { return x * x; }
};

However, there are various existing APIs (which I again do not control) that might return the C struct by value or that might use it as a member to some other aggregate data type. I therefore cannot force use of my wrapper class everywhere.

Is there a way to wrap the C struct such that conversions between it and the wrapper class are zero-cost? That is, I don't mind doing something like Wrapper(arrayOfBases[0]).square(), but I would prefer to avoid unnecessarily copying the Base object.

Ideally I'd do: static_cast<Wrapper&>(arrayOfBases[0]).square(), but my understanding is that such a downcast technically would be undefined behavior.

Another alternative I've considered is to replace inheritance with composition and a reference member, something like:

class Wrapper
{
public:
    Base& b;

    Wrapper(Base& b_) : b(b_) {}

    operator Base&() { return b; }
    operator const Base&() const { return b; }

    int square() const { return b.x * b.x; }
};

but I'm not sure how that could be done safely since it would open the door for dangling references.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • 5
    not everything must be a member. Once you give that up, you do not need the wrapper, and writing free funcitons has no cost for the object itself – 463035818_is_not_an_ai Feb 10 '23 at 09:22
  • Enable link-time optimisation (LTO)? – Paul Sanders Feb 10 '23 at 09:23
  • @463035818_is_not_a_number For my motivation, see [my earlier question](https://stackoverflow.com/q/75396027/). I also want to control the namespace where the `struct` (or in this case, the wrapper class) lives so that ADL can work. – jamesdlin Feb 10 '23 at 09:24
  • 1
    I think your last snippet is ok. I wouldnt be worried about dangling, the door is already open, not your fault ;). Name it `BaseReference` then the user knows that its a reference – 463035818_is_not_an_ai Feb 10 '23 at 09:25
  • 1
    Including a reference or const object in a class will prevent it from being assignable. This would cause a failure when sorting a vector of the class. This can be fixed in c++20 by writing a custom `operator=` but generally not earlier versions. – doug Feb 10 '23 at 18:20

0 Answers0