Re: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 07:29
Оценка: 9 (3) +1
Здравствуйте, Голощапов Александр, Вы писали:

ГА>Привет ALL!


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



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

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

ГА>template<class T> class C {
ГА>//...
        ~C()
        {
             sizeof(static_cast<A*>(reinterpret_cast<T*>(0)));
        }
ГА>}
ГА>


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


ГА>С уважением
Re[2]: проверка аргумента шаблона
От: Lorenzo_LAMAS  
Дата: 14.05.03 09:06
Оценка: +2
Позволю себе немного модифицировать твой пример.
template<class T>
class Checker{
public:
   Checker()
   {
       static_cast<A *>(static_cast<T*>(0));
   }
};

class B{};
Of course, the code must be complete enough to compile and link.
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[11]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 09:09
Оценка: 10 (1)
ДН>Ну раз ты про стримы вспомнил, начнем грязную войну — берем следующий код, пытаемся компилить, потом комментируем в деструкторе строку с кастами и раскомментируем с тайпдефом, компилируем. Потом думаем о том какое решение лучше. (мое имхо — каждое хорошо в определенной
ситуации)

Неверное использование virtual. Пожалуйста:

ДН>
ДН>class A
ДН>{
ДН>public:
ДН>  typedef int Derived_From_A;
ДН>  int a;
ДН>};
ДН>class B : virtual  public A { int b; };
ДН>class DA : virtual  public A {};
ДН>class DB : public B {};

ДН>class X : public DA, public DB {};

ДН>template <class T> class C
ДН>{
ДН>public:
ДН>  ~C()
ДН>  {
ДН>    //typedef T::Derived_From_A isGood;
ДН>    sizeof(static_cast<A*>(reinterpret_cast<T*>(0)));
ДН>  }
ДН>};

ДН>int main()
ДН>{
  C<X> cx;
ДН>  return 0;
ДН>}
ДН>
Re[5]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 10:11
Оценка: 3 (1)
ГА>Я тогда не очень понял что значит "вызывать ее в каждом конструкторе", ведь конструктор один. Или речь идет уже о производных классах от C?

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

А может без рантайма обойдемся?
class A
{
public:
  typedef int IAmGood;
};

class B : public A
{
};

class X {};

template <class T> class C
{
public:
  ~C() { typedef T::IAmGood isGood; }
};

int main()
{
  C<A> ca;
  C<B> cb;
  C<X> cx;
  return 0;
}
... << RSDN@Home 1.0 beta 6a >>
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;
};
--
Дмитрий
проверка аргумента шаблона
От: Голощапов Александр  
Дата: 14.05.03 07:19
Оценка:
Привет ALL!

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


class A {
//...
};

class B : public A {
//...
};

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


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

С уважением
Re: проверка аргумента шаблона
От: Bell Россия  
Дата: 14.05.03 07:32
Оценка:
Здравствуйте, Голощапов Александр, Вы писали:


class A {
//...
};

class B : public A {
//...
};

class E
{
};
template<class T> class C {
//...
public:
~C() { T* ptr_t = NULL; A* ptr_a = ptr_t; //Добавить внятный коментарий}
};

int main(int argc, char** argv)
{
C<A> ca;
C<B> cb;
C<E> ce;//error C2440: 'initializing' : cannot convert from 'class E *' to 'class A *'
//Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast 
//or function-style cast
return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[2]: проверка аргумента шаблона
От: Голощапов Александр  
Дата: 14.05.03 07:35
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

template<class T> class C {
//...
АШ>        ~C()
АШ>        {
АШ>             sizeof(static_cast<A*>(reinterpret_cast<T*>(0)));
АШ>        }
}


Общий смысл понятен, спасибо. А почему именно в деструкторе?

С уважением
Re[3]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 07:55
Оценка:
ГА>Общий смысл понятен, спасибо. А почему именно в деструкторе?

Несколько причин:

1) компилятор в любом случае генерирует код для деструктора
2) код проверки локализуется в одном месте. Можно было поступить иначе — создать статическую функцию с проверкой ограничений и вызывать ее в каждом конструкторе, но это менее надежное решение (вдруг при написании кода конструктора мы забудем, что нужно вызывать функцию проверки ограничений).
Re[3]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 07:57
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

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


ДН>А может без рантайма обойдемся?


О каком рантайме идет речь? Проверка осуществляется в компайлтайме.
Re[4]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 08:01
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

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


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


ДН>>А может без рантайма обойдемся?


АШ>О каком рантайме идет речь? Проверка осуществляется в компайлтайме.


Тьфу, я сам не знаю с чего я там "рантайм" написал — хотел написать "каст", но руки блин, совсем одемократились... Сорри. Читать как "А может без каста обойдемся?" Просто как то некрасиво, чисто имхо, два каста в одной строке как то некрасиво...
... << RSDN@Home 1.0 beta 6a >>
Re[4]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 08:03
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

ГА>>Общий смысл понятен, спасибо. А почему именно в деструкторе?


АШ>Несколько причин:


АШ>1) компилятор в любом случае генерирует код для деструктора

АШ>2) код проверки локализуется в одном месте. Можно было поступить иначе — создать статическую функцию с проверкой ограничений и вызывать ее в каждом конструкторе, но это менее надежное решение (вдруг при написании кода конструктора мы забудем, что нужно вызывать функцию проверки ограничений).

А можно было бы так (посмотрите мой пример):
template C<X>;


что вызовет явное инстанциирование шаблона и тогда не надо код проверки ни откуда вызывать. При явном инстанциировании инстанциируются все методы шаблона.
... << RSDN@Home 1.0 beta 6a >>
Re[5]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 08:11
Оценка:
Здравствуйте, Дмитрий Наумов, Вы писали:

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


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


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


ДН>>А может без рантайма обойдемся?


АШ>О каком рантайме идет речь? Проверка осуществляется в компайлтайме.


ДН>Тьфу, я сам не знаю с чего я там "рантайм" написал — хотел написать "каст", но руки блин, совсем одемократились... Сорри. Читать как "А может без каста обойдемся?" Просто как то некрасиво, чисто имхо, два каста в одной строке как то некрасиво...


А чем же это не красиво? Ведь ничего запрещенного код с кастами не делает. Опять же, оптимизатор этот код благополучно выкинет. А вот то, что ты меняешь интерфейс класс A только ради того, чтобы проверить "наследник или нет" заставляет задуматься над правильностью твоего решения, имхо.
Re[6]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 08:19
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>А чем же это не красиво? Ведь ничего запрещенного код с кастами не делает. Опять же, оптимизатор этот код благополучно выкинет. А вот то, что ты меняешь интерфейс класс A только ради того, чтобы проверить "наследник или нет" заставляет задуматься над правильностью твоего решения, имхо.


Ну если считать что trait это "изменение интерфейса", то ...
Я ж свое имхо высказал, что касты, особенно reinterpret_cast уж больно глаза режет.
... << RSDN@Home 1.0 beta 6a >>
Re[5]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 08:20
Оценка:
ДН>А можно было бы так (посмотрите мой пример):
ДН>
ДН>template C<X>;
ДН>


ДН>что вызовет явное инстанциирование шаблона и тогда не надо код проверки ни откуда вызывать. При явном инстанциировании инстанциируются все методы шаблона.


Да это же самоубийство!!!. Представь шаблон из 1000 методов.
Re[6]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 08:24
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

ДН>>А можно было бы так (посмотрите мой пример):

ДН>>
ДН>>template C<X>;
ДН>>


ДН>>что вызовет явное инстанциирование шаблона и тогда не надо код проверки ни откуда вызывать. При явном инстанциировании инстанциируются все методы шаблона.


АШ>Да это же самоубийство!!!. Представь шаблон из 1000 методов.


Опять ты в крайности ударяешься... Я предложил вариант к действию, а не инструкцию как делать ВСЕГДА.
... << RSDN@Home 1.0 beta 6a >>
Re[7]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 08:40
Оценка:
ДН>Опять ты в крайности ударяешься... Я предложил вариант к действию, а не инструкцию как делать ВСЕГДА.

Никаких крайностей. Твое решение нельзя рассматривать даже как вариант, потому что:

1) для обеспечения проверки ты изменяешь интерфейс класса A внося в него новое "свойство" (подставь вместо A std::istream_iterator и ты поймешь к чему я клоню)
2) для работоспособности твоего варианта необходимо явное инстанцирование (что само по себе рассточительно). Но представь, я забываю явно инстанцировать C<my_class>, причем my_class не является потомком A, и что? Да ничего. Класс С преспокойно берет my_class и начинает с ним работать (поскольку T::IsGood не будет генерироваться).

Внесены изменения автора. -- ПК.
Re[8]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 08:50
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

ДН>>Опять ты в крайности ударяешься... Я предложил вариант к действию, а не инструкцию как делать ВСЕГДА.


АШ>Никаких крайностей. Твое решение нельзя рассматривать даже как вариант, потому что:


АШ>1) для обеспечения проверки ты изменяешь интерфейс класса A внося в него новое "свойство" (подставь вместо A std::istream_iterator и ты поймешь к чему я клоню)


С этим я еще могу согласится, но только в случае если А — класс из библиотеки(или еще откуда нибудь), который мы не можем модифицировать.

АШ>2) для работоспособности твоего варианта необходимо явное инстанцирование (что само по себе рассточительно). Но представь, я забываю явно инстанцировать C<my_class>, причем my_class не является потомком A, и что? Да ничего. Класс С приспокойно берет my_class и начинает с ним работать (посколь T::IsGood не будет генерироваться).


АШ>


Оставь этот typedef в деструкторе и "забывчивость" не будет виновником появления ошибок.
... << RSDN@Home 1.0 beta 6a >>
Re[9]: проверка аргумента шаблона
От: Анатолий Широков СССР  
Дата: 14.05.03 08:54
Оценка:
ДН>С этим я еще могу согласится, но только в случае если А — класс из библиотеки(или еще откуда нибудь), который мы не можем модифицировать.

А так нам ничего не надо модифицировать.

АШ>2) для работоспособности твоего варианта необходимо явное инстанцирование (что само по себе рассточительно). Но представь, я забываю явно инстанцировать C<my_class>, причем my_class не является потомком A, и что? Да ничего. Класс С приспокойно берет my_class и начинает с ним работать (посколь T::IsGood не будет генерироваться).


АШ>


ДН>Оставь этот typedef в деструкторе и "забывчивость" не будет виновником появления ошибок.


Ну тогда и явного инстанцирования не надо будет, но по причине первой второе можно уже и не рассматривать.
Re[10]: проверка аргумента шаблона
От: Дмитрий Наумов  
Дата: 14.05.03 09:03
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

ДН>>С этим я еще могу согласится, но только в случае если А — класс из библиотеки(или еще откуда нибудь), который мы не можем модифицировать.


АШ>А так нам ничего не надо модифицировать.


АШ>>2) для работоспособности твоего варианта необходимо явное инстанцирование (что само по себе рассточительно). Но представь, я забываю явно инстанцировать C<my_class>, причем my_class не является потомком A, и что? Да ничего. Класс С приспокойно берет my_class и начинает с ним работать (посколь T::IsGood не будет генерироваться).


АШ>>


ДН>>Оставь этот typedef в деструкторе и "забывчивость" не будет виновником появления ошибок.


АШ>Ну тогда и явного инстанцирования не надо будет, но по причине первой второе можно уже и не рассматривать.


Ну раз ты про стримы вспомнил, начнем грязную войну — берем следующий код, пытаемся компилить, потом комментируем в деструкторе строку с кастами и раскомментируем с тайпдефом, компилируем. Потом думаем о том какое решение лучше. (мое имхо — каждое хорошо в определенной ситуации)
class A
{
public:
  typedef int Derived_From_A;
  int a;
};
class B : public A { int b; };
class DA : public A {};
class DB : public B {};

class X : virtual public DA, virtual public DB {};

template <class T> class C
{
public:
  ~C()
  {
    //typedef T::Derived_From_A isGood;
    sizeof(static_cast<A*>(reinterpret_cast<T*>(0)));
  }
};

int main()
{
  C<X> cx;
  return 0;
}
... << RSDN@Home 1.0 beta 6a >>
Re[4]: проверка аргумента шаблона
От: Голощапов Александр  
Дата: 14.05.03 09:53
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Несколько причин:

АШ>1) компилятор в любом случае генерирует код для деструктора
м... т.е. таким образом мы не обременим объект дополнительными функциями? или о чем речь?

АШ>2) код проверки локализуется в одном месте. Можно было поступить иначе — создать статическую функцию с проверкой ограничений и вызывать ее в каждом конструкторе, но это менее надежное решение (вдруг при написании кода конструктора мы забудем, что нужно вызывать функцию проверки ограничений).

т.е. что-то вроде этого ?
class A {
//...
};

class B : public A {
//...
};

template<class T> class C {
public:
    static void Check() {sizeof(static_cast<A*>(reinterpret_cast<T*>(0)));}
    C() 
    {
         Check();
         //...
    }
};


Я тогда не очень понял что значит "вызывать ее в каждом конструкторе", ведь конструктор один. Или речь идет уже о производных классах от C?

С уважением
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[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[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...
Пока на собственное сообщение не было ответов, его можно удалить.