[英]are member pointers fixed in size and reinterpret_cast?
我正在嘗試創建一個包含指向任意類實例和函數的指針的模板類,如下所示:
template<class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
FunctPtr functPtr_;
C* instPtr_;
public:
A(FunctPtr functPtr, C* instPtr)
: functPtr_(functPtr)
, instPtr_(instPtr) {}
};
但是,我希望能夠使用placement new創建此類的實例而無需動態分配內存。 C ++標准是否保證所有C類的模板類的大小都是固定的?
在Don Clugston的有關指針的文章中 ,我注意到了各種編譯器上成員函數指針的各種大小的圖表,並且一些編譯器的大小並不總是相同的。 我以為我被抽了水,但這符合標准嗎? 從C ++標准開始。 5.2.10關於重新解釋演員表:
—將類型為“指向成員函數的指針”的prvalue轉換為指向成員函數類型的不同指針,然后再返回其原始類型,將產生指向成員值的原始指針。
C ++標准中的該語句是否表示成員函數指針的大小相同?
如果不是這樣,我想我仍然可以按如下方式重寫代碼,以顯式地利用該reinterpret_cast保證:
class GenericClass;
template<class C>
class A {
typedef void (GenericClass::*GenFunctPtr)();
typedef void (C::*SpecificFunctPtr)();
GenFunctPtr functPtr_; //store any kind of function ptr in this fixed format
GenericClass* instPtr_;
public:
A(SpecificFunctPtr functPtr, C* instPtr)
: functPtr_(reinterpret_cast<GenFunctPtr>(functPtr))
, instPtr_(reinterpret_cast<GenericClass*>(instPtr)) {}
void DoSomething()
{
//now convert pointers back to the original type to use...
reinterpret_cast<SpecificFunctPtr>(functPtr_);
reinterpret_cast<C*>(instPtr_);
}
};
現在似乎要求它的大小都相同,但要符合標准,對嗎? 我更喜歡第一種選擇,但是如果我必須選擇第二種也可以。 思考?
我不知道是否在標准中指定了指向成員的指針的實現細節(找不到它),但是由於我們知道C*
對於所有C
都具有相同的大小,因此我們只需確定大小即可各種類型C
的FunctPtr
,只需添加一個static_assert
:
template <class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
static_assert(sizeof(FunctPtr) == 16,
"unexpected FunctPtr size"); // from coliru, clang and gcc
FunctPtr functPtr_;
C* instPtr_;
...
};
至少我用幾種類型的類({基本,派生,多個派生} x {虛擬,非虛擬})進行了嘗試,並且始終提供相同的大小。
這可能是特定於平台和/或編譯器的,因為指向成員函數的指針是非常奇怪的動物,它表明:
僅使用單一繼承的類的指向成員函數的指針的大小僅是指針的大小。
使用多重繼承的類的指向成員函數的指針的大小是指針的大小加上size_t的大小。
這不是我在clang或gcc中看到的。
Microsoft編譯器根據類的復雜程度使用不同大小的成員指針。 從技術上講,這是不合規的(因為即使在類定義不可見的情況下,您也可以定義指向成員的指針),但是在實踐中它可以很好地工作,默認情況下它們會這樣做。 實用程序和編譯器開關可用於控制此行為。 參見例如https://msdn.microsoft.com/en-us/library/83cch5a6.aspx 。
即使任何給定類的指針始終具有相同的大小,只是不同的類可能具有指向成員的大小不同的指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.