Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: Akon от Сентябрь 13, 2010, 13:54



Название: checkFirstBase<>()
Отправлено: Akon от Сентябрь 13, 2010, 13:54
Данный шаблон функции нужен для проверки корректности, если используется downcast с помощью reinterpret_cast<>() (в целях оптимизации). 

Код:
/// Checks that \a BaseT is first base class of \a DerivedT. Another words, the function template
/// checks whether casting from \a DerivedT down to \a BaseT can be safety performed through
/// reinterpret_cast<>() (instead of static_cast<>()), i.e.:
/// reinterpret_cast<BaseT*>(derived) == static_cast<BaseT*>(derived);
/// Example:
/// \code
/// class C: public A, public B { ... }
/// checkFirstBase<A>(C); // OK
/// checkFirstBase<B>(C); // runtime error
/// \endcode
/// \warning The function template assumes that compiler places in memory base classes in order of
/// declaration. This is not a requarement of the C++ Standard.
template <typename BaseT, typename DerivedT>
inline void checkFirstBase()
{
DerivedT* const Derived = reinterpret_cast<DerivedT*>(1);
Q_UNUSED(Derived);
Q_ASSERT(reinterpret_cast<void*>(1) == reinterpret_cast<void*>(static_cast<BaseT*>(Derived))
&& "DerivedT does not coincide with BaseT (BaseT is not first base class of DerivedT)");
}

По логике, такая проверка может быть осуществлена в compile-time. Но сходу у меня это сделать не получилось :(


Название: Re: checkFirstBase<>()
Отправлено: navrocky от Сентябрь 15, 2010, 00:26
Код:
<<<
/// checkFirstBase<A>(C); // OK
/// checkFirstBase<B>(C); // runtime error
>>>
/// checkFirstBase<A, C>(); // OK
/// checkFirstBase<B, C>(); // runtime error

Может привести к виду safe_reinterpret_cast<B>(a) как в остальных случаях?

Цитировать
По логике, такая проверка может быть осуществлена в compile-time. Но сходу у меня это сделать не получилось :(

boost::is_base_of что-то похожее, можно почерпнуть оттуда идею.


Название: Re: checkFirstBase<>()
Отправлено: Akon от Сентябрь 15, 2010, 11:55
Цитировать
Может привести к виду safe_reinterpret_cast<B>(a) как в остальных случаях?
Да

Цитировать
boost::is_base_of что-то похожее, можно почерпнуть оттуда идею.
boost::type_traits мне не помог (мож чего проглядел).
boost::is_base_of в таких случаях, при downcast, всегда будет говорить "да". Важно установить, что при downcast'e к базовому классу численное значение указателя не изменится.
Код:
class A {...};
class B {...};
class C : public A, public B {...};

C c;

B* pb = &c;
C* pc = &c;

void* pb_value = reinterpret_cast<void*>(pb);
void* pc_value = reinterpret_cast<void*>(pc);

assert(pb == pc);  // не вопрос
assert(pb_value == pc_value);  // Опс

Т.е. в то время как сами указатели равны (pb == pc), их численные значения в общем случае не равны (pb_value != pc_value).


Название: Re: checkFirstBase<>()
Отправлено: navrocky от Сентябрь 15, 2010, 12:11
Цитировать
boost::type_traits мне не помог (мож чего проглядел).
boost::is_base_of в таких случаях, при downcast, всегда будет говорить "да".
Я тоже ничего не нашел, но я имел ввиду что можно подсмотреть идею там и попытаться сделать свое.