0

Question:

We do have a template based class, that provides some functionality around a primitive type (e.g. serializing, deserializing, ...)

template <typename PRIM_TYPE> class WrappedPrimitive
{
public:
    PRIM_TYPE v;

    //lots of other methods, including serialization and deserialization

    PRIM_TYPE & operator= (const PRIM_TYPE & value) { v = value; return v; }
    operator PRIM_TYPE() const          { return v; }
};
typedef WrappedPrimitive<float>        WrappedPrimitiveFloat;

Let's say I have a function

void maninpulateFloat(float *f) {*f = 5.0f;}

Is there any way to add some class function, such that it returns the address of the vmember when casting from *WrappedPrimitiveFloat to *float. (Or in general from *WrappedPrimitive<PRIM_TYPE> to *PRIM_TYPE?

WrappedPrimitiveFloat myfloat;
manipulateFloat(&myfloat.v) // This works
manipulateFloat(&myfloat)   // Is there any way to make this work?

Background:

I know it is maybe not a good idea, but the reason I'd like it is because we ported the code to Linux, where myfloat will actually be a float and not some wrapped value. Right now, we need to distinguish these places with

#ifdef _WIN32
manipulateFloat(&myfloat.v)
#else
manipulateFloat(&myfloat)
#endif

which is also really ugly. Alternatively, I'd be happy with a line of code that works on both Windows/Linux.

What I have tried

It is possible to overload the operator& function,

PRIM_TYPE * operator& () {return &v;}

but according to this post Overloading unary operator & it is not the best idea, as using & will always return a PRIM_TYPE*.

Community
  • 1
  • 1
kiki
  • 325
  • 6
  • 20
  • What's the problem with overloading `operator&`? – Kerrek SB Oct 16 '14 at 12:56
  • 1
    If your function took the float by reference, you could add `operator TYPE&()` If not you will have to store a float (value or reference) in a local variable first. – Neil Kirk Oct 16 '14 at 13:10
  • @KerrekSB Do you recommend overloading `operator&` for every class that has a conversion operator? – Neil Kirk Oct 16 '14 at 13:11
  • Unfortunately, I cannot change the function to take a reference instead of a pointer. In case of a local variable, I will of course have to write it back to the original afterwards, as it will get manipulated. – kiki Oct 16 '14 at 13:17
  • @NeilKirk: No, I recommend shooting on sight everyone who overloads `operator&`. But that wasn't the question... – Kerrek SB Oct 16 '14 at 15:02

1 Answers1

0

You can implement a template get_address() function and use it everywhere you need instead of unary &:

template <typename PRIM_TYPE> class WrappedPrimitive
{
public:
    operator PRIM_TYPE() const { return v; }

    // these conversions are necessary to implement
    operator PRIM_TYPE&() { return v; }
    operator const PRIM_TYPE&() const { return v; } 
};


template <typename PRIM_TYPE>
PRIM_TYPE* get_address(PRIM_TYPE& v) {
    return &v;
}

template <typename PRIM_TYPE>
PRIM_TYPE* get_address(WrappedPrimitive<PRIM_TYPE>& wp) {
    return &static_cast<PRIM_TYPE&>(wp);
}

template <typename PRIM_TYPE>
const PRIM_TYPE* get_address(const WrappedPrimitive<PRIM_TYPE>& wp) {
    return &static_cast<const PRIM_TYPE&>(wp);
}

Demo

Anton Savin
  • 40,838
  • 8
  • 54
  • 90