Проблема связана с макетом памяти. Стандарт не гарантирует многого о расположении памяти, в частности он не гарантирует, что не существует смещения между производным и базовым классом ...
Например:
class Foo: public boost::noncopyable
{
public:
virtual ~Foo();
};
Поскольку boost::noncopyable
не имеет метода virtual
, в gcc (void*)(Foo*)&f
и (void*)(boost::noncopyable*)&f
будут разные значения.
Но на практике это не имеет большого значения, потому что компилятор выполнит необходимые настройки. То есть, если вы сравните только Foo*
, вы должны быть в порядке и денди ...
... Помимо того, что множественное наследование может нарушить это, если в вашей иерархии есть несколько Foo
подобъектов.
С другой стороны, вы должны быть в одном из двух случаев:
- либо нет иерархии (нет виртуальной), а затем вы можете сравнить адрес объектов как
- или существует иерархия (и виртуальный метод), и вы используете
dynamic_cast<void*>(&f)
, чтобы получить адрес всего объекта.
Следовательно, в качестве шаблонного метода это даст:
template <typename T, typename U>
bool have_same_dynamic_location(T const& t, U const& u)
{
return dynamic_cast<void*>(&t) == dynamic_cast<void*>(&u);
}
(который действителен, только если T и U имеют виртуальные методы)