Использую CRTP. В коде это выглядит так:
template
class Base{
//...
};
class Derived : public Base{
//...
};
Начали появляться copy/paste ошибки:
class Foo : public Base{
//...
};
class Bar : public Base{ //Ой
//...
};
Решил написать ассерт, который бы это дело проверял.
Придумал такой вариант:
template
class Base{
protected:
typedef T TemplateType;
typedef Base BaseType;
//...
};
class Derived : public Base{
public:
Derived(){
Q_ASSERT(typeid(*this) == typeid(Base::TemplateType));
}
//...
};
Но какой-то он неказистый. Работает на этапе выполнения, требует наличия каких-то непонятных тайпдефов.
И вот я здесь. Как написать такой ассерт используя C++03 и Qt? И чтобы его при этом было не стыдно людям показать.
Ответ
Такой вариант:
template
class IsDerivedFrom
{
class No {};
class Yes { No no[2]; };
static Yes Test(B*);
static No Test(...);
public:
enum { Is = sizeof(Test(static_cast(0)))==sizeof(Yes) };
};
template
class Base
{
};
class D1: public Base
{
public:
D1(){
cout << IsDerivedFrom >::Is << endl;
}
};
class D2: public Base
{
public:
D2() {
cout << IsDerivedFrom >::Is << endl;
}
};
int main()
{
D1 d1;
D2 d2;
}
Ну, понятно, что можно использовать IsDerivedFrom >::Is прямо во время компиляции.
Условие C++03 выполнено - Open Watcom успешно справился с компиляцией.
Update Решение 2. Не даст скомпилировать наследника от другого Base<>, copy-paste отработает - имени текущего класса в нем нет :). Увы, один typedef все же потребовался.
template
class Base
{
typedef T base;
};
template
class IsDerivedFromBase
{
static void Constraints(T*p)
{
Base*b = p;
}
public:
IsDerivedFromBase() { void(*p)(T*) = Constraints; }
};
class D1: public Base
{
public:
D1(){
IsDerivedFromBaseid;
}
};
class D2: public Base
{
public:
D2() {
IsDerivedFromBaseid;
}
};
int main()
{
D1 d1;
D2 d2;
}
Update 2 Пробуйте теперь:
template
class IsSame
{
public:
enum { value = 0 };
};
template
class IsSame
{
public:
enum { value = 1 };
};
template
class Base
{
typedef T base;
};
template
class IsDerivedFromBaseThis
{
static void Constraints(T*p)
{
Base*b = p;
}
public:
template
IsDerivedFromBaseThis(U*) {
int x[IsSame::value];
void(*p)(T*) = Constraints;
}
};
class D1: public Base
{
public:
D1(){
IsDerivedFromBaseThisid(this);
}
};
class D2: public Base
{
public:
D2() {
IsDerivedFromBaseThisid(this);
}
};
int main()
{
D1 d1;
D2 d2;
}
Комментариев нет:
Отправить комментарий