我正在尝试创建一个模板类,其中包含指向任意类实例和函数的指针,如下所示:
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's article关于指针,我注意到各种编译器上的成员函数指针的各种大小的图表,一些编译器的大小并不总是相同。我以为我被冲洗了,但这个标准符合吗?来自 C++ 标准 sec。 5.2.10 关于重新解释:
——将“指向成员函数的指针”类型的纯右值转换为指向成员函数的不同指针 类型并返回其原始类型产生指向成员值的原始指针。
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_;
...
};
至少我尝试了几种类型的类({base, derived, multiple derived} x {virtual, non-virtual})并且它总是给出相同的大小。
这可能是特定于平台和/或编译器的,如Pointers to member functions are very strange animals表示:
The size of a pointer-to-member-function of a class that uses only single inheritance is just the size of a pointer.
The size of a pointer-to-member-function of a class that uses multiple inheritance is the size of a pointer plus the size of a size_t.
这不是我在 clang 或 gcc 中看到的。
关于c++ - 成员指针的大小和 reinterpret_cast 是否固定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29457915/