Re: проверка аргумента шаблона
От: Юнусов Булат Россия  
Дата: 14.05.03 09:58
Оценка:
Здравствуйте, Голощапов Александр, Вы писали:

Что то типа такого.
#include <TypeManip.h>

class A {
};

class B : public A {
};

template <class T>
class C {
    char check[SUPERSUBCLASS(A, T)];
};

int main(int argc, char* argv[])
{
    C<B> good;
    C<int> bad;
    
    return 0;
}


PS в vc6 выдается варнинг "nonstandard extension used : zero-sized array" вместо ошибки
Re[5]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 10:11
Оценка: 3 (1)
ГА>Я тогда не очень понял что значит "вызывать ее в каждом конструкторе", ведь конструктор один. Или речь идет уже о производных классах от C?

Число конструкторов не ограничено (то есть, потенциально может быть создано неограниченное число конструкторов класса и в каждый из них надо не забыть поместить вызов Check(), поскольку будет существовать столько путей создания объекта сколько конструкторов было объявлено (явно или не явно)), а деструктор всего один. Вот мы и использует этот факт и именно в деструкторе размещаем код проверки. Помимо этого, компилятор, инстанцируя шаблон, генерирует только необходимые методы (если, конечно, не указано явное инстанцирование), но так как стандарт гарантирует обязательный вызов деструктора объекта перед его уничтожением, то код деструктора будет генерироваться всегда, что нам и нужно для гарантии проверки требований.
Re[2]: проверка аргумента шаблона
От: Дмитро  
Дата: 14.05.03 10:23
Оценка: +1
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, Голощапов Александр, Вы писали:


ЮБ>Что то типа такого.

ЮБ>
ЮБ>template <class T>
ЮБ>class C {
ЮБ>    char check[SUPERSUBCLASS(A, T)];
ЮБ>};
ЮБ>


ЮБ>PS в vc6 выдается варнинг "nonstandard extension used : zero-sized array" вместо ошибки


А лучше даже так (чтобы не добавлять лишних полей):
template <class T>
class C {
    typedef char T_should_be_a_subclass_of_A[1][SUPERSUBCLASS(A, T)] COMPILE_TIME_ASSERTION_FOR_C;
};
--
Дмитрий
Re[6]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 10:23
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>деструктор всего один. Вот мы и использует этот факт и именно в деструкторе размещаем код проверки


Интересно, а что будет если объект аллокирован на куче, а вызвыть delete для него пользователь забыл? Проверки не будет?
... << RSDN@Home 1.0 beta 6a >>

Удалено избыточное цитирование. -- ПК.
Re[6]: проверка аргумента шаблона
От: Голощапов Александр  
Дата: 14.05.03 10:24
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Число конструкторов не ограничено (то есть, потенциально может быть создано неограниченное число конструкторов класса и в каждый из них надо не забыть поместить вызов Check(), поскольку будет существовать столько путей создания объекта сколько конструкторов было объявлено (явно или не явно)), а деструктор всего один. Вот мы и использует этот факт и именно в деструкторе размещаем код проверки. Помимо этого, компилятор, инстанцируя шаблон, генерирует только необходимые методы (если, конечно, не указано явное инстанцирование), но так как стандарт гарантирует обязательный вызов деструктора объекта перед его уничтожением, то код деструктора будет генерироваться всегда, что нам и нужно для гарантии проверки требований.


Огромное спасибо, все понятно.

С уважением
Re[7]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 11:43
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>Здравствуйте, Анатолий Широков, Вы писали:


АШ>деструктор всего один. Вот мы и использует этот факт и именно в деструкторе размещаем код проверки


ДН>Интересно, а что будет если объект аллокирован на куче, а вызвыть delete для него пользователь забыл? Проверки не будет?


По-моему, undefined behavior по

3.8

4. A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which object occupied is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

Re[8]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 11:55
Оценка:
Здравствуйте, Анатолий Широков,

тут смысл не в том что это ill-formed или нет, понятно что это баг. Но, проблема в том, что одна ошибка программиста — забыл вызвать delete, повлечет еще одну, возможно более серьезную проблему — проверка на то, что шаблон параметризирован наследником от ... не будет выполнятся.
... << RSDN@Home 1.0 beta 6a >>
Re[3]: проверка аргумента шаблона
От: MaximE Великобритания  
Дата: 14.05.03 12:47
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

LL>Позволю себе немного модифицировать твой пример.


Мне можно?

template<class T>
class Checker{
public:
   Checker()
   {
       typedef T* P;
       static_cast<A*>(P());
   }
};
Re[9]: проверка аргумента шаблона
От: UgN  
Дата: 14.05.03 12:55
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

ДН>тут смысл не в том что это ill-formed или нет, понятно что это баг. Но, проблема в том, что одна ошибка программиста — забыл вызвать delete, повлечет еще одну, возможно более серьезную проблему — проверка на то, что шаблон параметризирован наследником от ... не будет выполнятся.


Почему? Проверка будет идти на этапе компиляции, когда дело дойдет до деструктора, который будет обязательно: либо самописный либо генеренный.
А уж вызывается этот деструктор где-нибудь или нет, имхо, дело десятое и на проверку не влияет.
Re: проверка аргумента шаблона
От: WFrag США  
Дата: 14.05.03 14:13
Оценка: 14 (1)
Здравствуйте, Голощапов Александр, Вы писали:

Можно так (в тело класса):

enum { is_T_derived_from_A = boost::is_base_and_derived< A, T >::value };
BOOST_STATIC_ASSERT( is_T_derived_from_A );
7. О чем невозможно говорить, о том следует молчать.
Re[2]: проверка аргумента шаблона
От: Кодт Россия  
Дата: 14.05.03 15:43
Оценка:
Здравствуйте, WFrag, Вы писали:

WF>enum { is_T_derived_from_A = boost::is_base_and_derived< A, T >::value };

WF>BOOST_STATIC_ASSERT( is_T_derived_from_A );

А чтобы не тащить весь boost, -- подсмотрите, как там это сделано и оставьте себе.
(=^.^=) Neko ... << RSDN@Home 1.0 beta 7a >>
Перекуём баги на фичи!
Re[3]: проверка аргумента шаблона
От: MaximE Великобритания  
Дата: 14.05.03 18:08
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, WFrag, Вы писали:


WF>enum { is_T_derived_from_A = boost::is_base_and_derived< A, T >::value };

WF>BOOST_STATIC_ASSERT( is_T_derived_from_A );

К>А чтобы не тащить весь boost, -- подсмотрите, как там это сделано и оставьте себе.


Можно и у Страуструпа посмотреть:


    template<class T, class B> struct Derived_from {
        static void constraints(T* p) { B* pb = p; }
        Derived_from() { void(*p)(T*) = constraints; }
    };

    template<class T1, class T2> struct Can_copy {
        static void constraints(T1 a, T2 b) { T2 c = a; b = a; }
        Can_copy() { void(*p)(T1,T2) = constraints; }
    };

    template<class T1, class T2 = T1> struct Can_compare {
        static void constraints(T1 a, T2 b) { a==b; a!=b; a<b; }
        Can_compare() { void(*p)(T1,T2) = constraints; }
    };

    template<class T1, class T2, class T3 = T1> struct Can_multiply {
        static void constraints(T1 a, T2 b, T3 c) { c = a*b; }
        Can_multiply() { void(*p)(T1,T2,T3) = constraints; }
    };
Re[10]: проверка аргумента шаблона
От: Дмитро  
Дата: 15.05.03 01:13
Оценка:
Здравствуйте, UgN, Вы писали:

UgN>Здравствуйте, Дмитрий Наумов, Вы писали:


ДН>тут смысл не в том что это ill-formed или нет, понятно что это баг. Но, проблема в том, что одна ошибка программиста — забыл вызвать delete, повлечет еще одну, возможно более серьезную проблему — проверка на то, что шаблон параметризирован наследником от ... не будет выполнятся.


UgN>Почему? Проверка будет идти на этапе компиляции, когда дело дойдет до деструктора, который будет обязательно: либо самописный либо генеренный.

UgN>А уж вызывается этот деструктор где-нибудь или нет, имхо, дело десятое и на проверку не влияет.

Эксперимент показывает, что VC7 не инстанцирует деструктор, если он не вызывается.
--
Дмитрий
Re[3]: проверка аргумента шаблона
От: Дмитро  
Дата: 15.05.03 01:15
Оценка:
Небольшая поправка:

Вместо
    typedef char T_should_be_a_subclass_of_A[1][SUPERSUBCLASS(A, T)] COMPILE_TIME_ASSERTION_FOR_C;


должно быть
    typedef char T_should_be_a_subclass_of_A[1][SUPERSUBCLASS(A, T)];
--
Дмитрий
Re: проверка аргумента шаблона
От: iFuzzy Украина  
Дата: 15.05.03 07:04
Оценка:
Здравствуйте, Голощапов Александр, Вы писали:

ГА>Привет ALL!


ГА>допустим есть такая ситуация:



ГА>
ГА>class A {
ГА>//...
ГА>};

ГА>class B : public A {
ГА>//...
ГА>};

ГА>template<class T> class C {
ГА>//...
ГА>}
ГА>


ГА>Каким образом можно ограничить использование класса C, чтобы в качестве аргумента шаблона T можно было использовать только наследников A ?


ГА>С уважением



template<class Potomok, class Predok>
class isDerived
{
private:

//Определение не требуется
  static char    discriminator(...);
  static double  discriminator(Predok*);
  static Potomok* d;

public:

  enum { value = ( sizeof(discriminator(d)) != sizeof(char) ) };
};


#define IS_DERIVED(Potomok, Predok) isDerived< Potomok, Predok >::value


//Ваш случай.
template<class T> class C 
{

private:
    #ifdef _DEBUG
        char blocker[IS_DERIVED(T, A)];
    #endif
};


Всё считается на этапе компиляции. Правда работает только для public-наследования.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.