我需要一種方法來驗證編譯期間指向另一個類(派生或基地)的指針的upcast/downcast不會更改指針值。也就是說,演員陣容相當於reinterpret_cast
。如何在編譯時驗證reinterpret_cast的有效性
具體來說,情況如下:我有一個Base
類和一個Derived
類(顯然來自Base
)。還有一個模板Wrapper
類,它由指向作爲模板參數指定的類的指針組成。
class Base
{
// ...
};
class Derived
:public Base
{
// ...
};
template <class T>
class Wrapper
{
T* m_pObj;
// ...
};
在一些情況下,我有Wrapper<Derived>
類型的變量,我想打電話接收RO Wrapper<Base>
一個(常數)參照的功能。顯然這裏沒有自動投射,Wrapper<Derived>
不是從Wrapper<Base>
派生。
void SomeFunc(const Wrapper<Base>&);
Wrapper<Derived> myWrapper;
// ...
SomeFunc(myWrapper); // compilation error here
在標準C++的範圍內有辦法處理這種情況。像這樣的例子:
Derived* pDerived = myWrapper.Detach();
Wrapper<Base> myBaseWrapper;
myBaseWrapper.Attach(pDerived);
SomeFunc(myBaseWrapper);
myBaseWrapper.Detach();
myWrapper.Attach(pDerived);
但我不喜歡這個。這不僅需要一個尷尬的語法,而且還會產生一個額外的代碼,因爲Wrapper
有一個不平凡的地方(正如你可能猜到的),並且我正在使用異常處理。 OTOH如果指向Base
和Derived
的指針是相同的(就像在這個例子中一樣,因爲沒有多重繼承) - 人們可以將myWrapper
轉換爲所需的類型,並調用SomeFunc
,它將工作!
因此,我已經添加了以下到Wrapper
:
template <class T>
class Wrapper
{
T* m_pObj;
// ...
typedef T WrappedType;
template <class TT>
TT& DownCast()
{
const TT::WrappedType* p = m_pObj; // Ensures GuardType indeed inherits from TT::WrappedType
// The following will crash/fail if the cast between the types is not equivalent to reinterpret_cast
ASSERT(PBYTE((WrappedType*)(1)) == PBYTE((TT::WrappedType*)(WrappedType*)(1)));
return (TT&) *this; // brute-force case
}
template <class TT> operator const Wrapper<TT>&() const
{
return DownCast<Wrapper<TT> >();
}
};
Wrapper<Derived> myWrapper;
// ...
// Now the following compiles and works:
SomeFunc(myWrapper);
的問題是,在某些情況下蠻力投無效。例如,在這種情況下:
class Base
{
// ...
};
class Derived
:public AnotherBase
,public Base
{
// ...
};
這裏指針到Base
的值不同於Derived
。因此Wrapper<Derived>
不等於Wrapper<Base>
。
我想檢測並防止這種無效沮喪的企圖。我已經添加了驗證(如您所見),但它在運行時間中有效。也就是說,代碼將被編譯和運行,並且在運行時會在調試版本中發生崩潰(或失敗的斷言)。
這很好,但我想在編譯期間抓住這一點,並且失敗了構建。一種STATIC_ASSERT。
有沒有辦法做到這一點?
也許在這裏使用'static_cast' return(TT&)* this; //蠻力案件'而不是c-cast可能會有所幫助,c-cast可能會做reinterpret_cast,這確實會破壞一切。如果兩個類共享繼承,編譯器應該用'static_cast'指向正確的地方。 – RedX
@RedX:在這個特定的地方,這相當於'static_cast',因爲rwo類'Wrapper '和'Wrapped '不相關 –
valdo