Я пытаюсь создать шаблонный класс, который содержит указатель на экземпляр произвольного класса и функции следующим образом:являются фиксированными размерами указателей и 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) {}
};
Однако, я хочу, чтобы иметь возможность создавать экземпляры этого класса без динамического выделения памяти с помощью размещения новый. Стандарт C++ гарантирует, что этот класс шаблона имеет фиксированный размер для всех классов C?
В Don Clugston's article на указателях Я заметил диаграмму различных размеров для указателей функций-членов на разных компиляторах, а несколько компиляторов не всегда одинакового размера. Я думал, что я был укушен, но соответствует ли это стандартам? Из стандарта C++ sec. 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_);
}
};
Теперь это, казалось бы, должны быть одинакового размера, и все же быть соответствуют стандартам , правильно? Я предпочел бы первый вариант, однако, если я тоже должен работать 2-й. Мысли?
Стандарт даже не гарантирует, что 'C *' имеет одинаковый размер для всех 'C' (хотя он находится на обязательных платформах) - хотя он гарантирует, что вы можете совершить кругосветное путешествие через' void * '. Я также думаю, что это позволяет изменять любые вставленные дополнения. Если вам нужна полная мобильность, я думаю, вам не повезло - хотя я думаю, что ваш механизм будет работать на большинстве платформ. –