Сделать взаимозаменяемые типы классов только путем приведения указателя, без необходимости выделять какие-либо новые объекты?

UPDATEЯ действительно ценю "не хочу этого, хочу этого вместо этого" предложения. Они полезны, особенно если они представлены в контекстемотивирующий сценарий, Тем не менее ... независимо от добра / зла, мне стало любопытно быстро и быстро найти"yes that can be done legally in C++11" против"no it is not possible to do something like that".

Я хочу "псевдоним" указатель объекта в качестве другого типа, дляsole purpose добавить некоторые вспомогательные методы. Псевдоним не может добавлять члены данных в базовый класс (на самом деле, чем больше я могу предотвратить это, тем лучше!) Все псевдонимы одинаково применимы к любому объекту этого типа ... это просто полезно, если система типов может подсказка, какой псевдоним, вероятно, является наиболее подходящим.

Не должно быть никакой информации о каком-либо конкретном псевдониме, который когда-либо кодируется в базовом объекте. Следовательно, я чувствую, что вы должны быть в состоянии "обмануть" система типов и просто пусть это будет аннотация ... проверяется во время компиляции, но в конечном итоге не имеет отношения к приведению во время выполнения. Что-то в этом роде:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Под капотом заводской метод на самом деле делаетNodeBase класс, а затем с помощью аналогичногоreinterpret_cast вернуть его какNode<AccessorFoo>*.

Самый простой способ избежать этого - создать легкие классы, которые обертывают узлы и передаются по значению. Таким образом, вам не нужно приводить, просто классы Accessor, которые используют дескриптор узла для переноса в своем конструкторе:

AccessorFoo foo (NodeBase::createViaFactory());
AccessorBar bar (foo.getNode());

Но если мне не нужно платить за все это, я не хочу. Это может включать, например, создание специального типа средства доступа для каждого вида обернутых указателей (AccessorFooShared, AccessorFooUnique, AccessorFooWeak и т. Д.). Предпочтительно, чтобы эти типизированные указатели были псевдонимами для одного идентификатора объекта, основанного на указателе, и были бы предпочтительны. хорошая ортогональность.

Итак, вернемся к этому первоначальному вопросу:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Похоже, есть какой-то способ сделать это, который может быть уродливым, но не "нарушать правила". В соответствии сISO14882: 2011 (e) 5.2.10-7:

An object pointer can be explicitly converted to an object pointer of a different type.70 When a prvalue v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast(static_cast(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

Бурение в определении& quot; класс стандартной компоновки & quot;, мы нашли:

has no non-static data members of type non-standard-layout-class (or array of such types) or reference, and has no virtual functions (10.3) and no virtual base classes (10.1), and has the same access control (clause 11) for all non-static data members, and has no non-standard-layout base classes, and either has no non-static data member in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and has no base classes of the same type as the first non-static data member.

Похоже, работа с чем-то вроде этого немного связывает мои руки без виртуальных методов в средствах доступа или узле. Тем не менее, C ++ 11, очевидно, имеетstd::is_standard_layout держать вещи проверенными.

Можно ли это сделать безопасно? Кажется, работает в gcc-4.7, но я хотел бы убедиться, что я не вызываю неопределенное поведение.

Ответы на вопрос(4)

Ваш ответ на вопрос