2014-10-16 2 views
0

Вопрос:Casting указатель базового класса указателю члена класса

У нас есть шаблон класса на основе, что обеспечивает некоторую функциональность вокруг примитивного типа (например, сериализации, десериализации, ...)

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; 

Скажем, у меня есть функция

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

есть ли способ, чтобы добавить некоторые функции класса, таким образом, что он возвращает ADDR ess члена v при литье от *WrappedPrimitiveFloat до *float. (Или вообще от *WrappedPrimitive<PRIM_TYPE> к *PRIM_TYPE

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

фона:

Я знаю, что это, возможно, не очень хорошая идея, но причина, я хотел бы это, потому что мы портировали код Linux , где myfloat фактически будет поплавок, а не какое-то завернутые значение. на данный момент мы должны различать эти места с

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

, который также очень некрасиво. с другой стороны, я был бы счастлив с линией код, который работает как на Windows/Linux.

То, что я пытался

можно перегрузить функцию оператора &,

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

но согласно этому сообщению Overloading unary operator & это не лучшая идея, поскольку использование & всегда будет возвращать a PRIM_TYPE*.

+0

чем проблема с перегрузкой 'оператор &'? –

+1

Если ваша функция взяла поплавок по ссылке, вы можете добавить 'operator TYPE &()' Если нет, вам сначала нужно будет сохранить float (значение или ссылку) в локальной переменной. –

+0

@KerrekSB Рекомендуете ли вы перегружать 'operator &' для каждого класса с оператором преобразования? –

ответ

0

Вы можете реализовать функцию шаблона get_address() и использовать его везде вам нужно вместо одноместной &:

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

Смежные вопросы