проверка аргумента шаблона
От: Голощапов Александр  
Дата: 14.05.03 07:19
Оценка:
Привет ALL!

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


class A {
//...
};

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

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


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

С уважением
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: проверка аргумента шаблона
От: 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[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[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[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[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[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?

С уважением
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.