Форум программистов, компьютерный форум CyberForum.ru

Как сделать шаблон, с параметром-классом - потомком определённого класса? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
18.01.2012, 14:32     Как сделать шаблон, с параметром-классом - потомком определённого класса? #1
Хочется сделать шаблон с параметром-классом, который обязан реализовывать определённый интерфейс.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class IService
{
public:
  virtual int main () = 0;
  virtual void handler (int) = 0;
};
 
template <class Service>
class ServiceHelper
{
public:
  void start ();
   //...
private:
  Service s;
  //...
};
Можно ли это как-то сделать?

Может это и не нужно?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.01.2012, 14:32     Как сделать шаблон, с параметром-классом - потомком определённого класса?
Посмотрите здесь:

C++ описание класса определённого типа
как в конструкторе класса передать параметром указатель на функцию? C++
Как правильно сделать шаблон класса complex C++
Как создать шаблон класса одномерного динамического массива? C++
Шаблоны функций, Ошибка: для использования класса шаблон требуется список аргументов шаблон C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
cyberobot
 Аватар для cyberobot
15 / 15 / 1
Регистрация: 01.09.2011
Сообщений: 66
18.01.2012, 16:12     Как сделать шаблон, с параметром-классом - потомком определённого класса? #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class IService
{
public:
  virtual int main () = 0;
  virtual void handler (int) = 0;
};
 
template <class Service>
class ServiceHelper:public Service
{
public:
  void start ();
   //...
private:
  Service s;
  //...
};
и теперь он кажется должен наследовать шаблонный класс
сам не проверял ещё
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
18.01.2012, 18:24     Как сделать шаблон, с параметром-классом - потомком определённого класса? #3
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <type_traits>
 
class Interface {
public:
    virtual void operator () const = 0;
    virtual ~Interface() {};
};
 
template<typename InterfaceImplementation>
class UsingInterface {
static_assert(std::is_base_of<Interface, InterfaceImplementation>::value, "Параметр должен быть потомком Interface");
public:
    void foo() const {ir();}
private:
    InterfaceImplementation ir;
};
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
19.01.2012, 13:56  [ТС]     Как сделать шаблон, с параметром-классом - потомком определённого класса? #4
О! Спасибо огромное! То, что доктор прописал!
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.01.2012, 15:31     Как сделать шаблон, с параметром-классом - потомком определённого класса? #5
Цитата Сообщение от Nick Alte Посмотреть сообщение
static_assert(std::is_base_of<Interface, InterfaceImplementation>::value, "Параметр должен быть потомком Interface");
1. Требуется новый стандарт или буст,
2. Это будет проверка времени выполнения, а не компиляции.

Добавлено через 5 минут
is_base_of может быть имплементиован подобным образом.
C++
1
2
3
4
5
6
7
8
9
10
11
template<typename Base, typename Derived>
struct is_base_of {
 private:
  static Derived* m_d;
  static char check( Base* );
  static long check( ... );
 public:
  enum {
    value = ( sizeof(check( m_d )) == sizeof(char) )
  };
};
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 16:23     Как сделать шаблон, с параметром-классом - потомком определённого класса? #6
Цитата Сообщение от lemegeton Посмотреть сообщение
1. Требуется новый стандарт или буст,
2. Это будет проверка времени выполнения, а не компиляции.

Добавлено через 5 минут
is_base_of может быть имплементиован подобным образом.
C++
1
2
3
4
5
6
7
8
9
10
11
template<typename Base, typename Derived>
struct is_base_of {
 private:
  static Derived* m_d;
  static char check( Base* );
  static long check( ... );
 public:
  enum {
    value = ( sizeof(check( m_d )) == sizeof(char) )
  };
};
хм...
а такое вообще возможно?
ведь значение value вычисляться будет на этапе компиляции
значит check тоже должна вычисляться на этапе компиляции
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.01.2012, 16:26     Как сделать шаблон, с параметром-классом - потомком определённого класса? #7
Цитата Сообщение от retmas Посмотреть сообщение
хм...
а такое вообще возможно?
ведь значение value вычисляться будет на этапе компиляции
значит check тоже должна вычисляться на этапе компиляции
Этот код я привел для тех, у кого нет буста/нового стандарта. Примерно так is_base_of и реализован в бусте.
Это вычисляется на этапе компиляции.
Пригодно для проверки во время выполнения.
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 16:30     Как сделать шаблон, с параметром-классом - потомком определённого класса? #8
и как можно применить ШМП (вычисления которого происходят на этапе компиляции) для вычисления результатов во время выполнения?
или я вас не так понял?
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.01.2012, 16:45     Как сделать шаблон, с параметром-классом - потомком определённого класса? #9
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdexcept>
 
template<typename Base, typename Derived>
struct is_base_of {
 private:
  static Derived* m_d;
  static char check( Base* );
  static long check( ... );
 public:
  enum {
    value = ( sizeof(check( m_d )) == sizeof(char) )
  };
};
 
class A {};
class B : public A {};
class D {};
 
int main(int argc, char *argv[]) {
  if (!is_base_of<A, B>::value) // вычисляется compiletime
    throw std::runtime_error("Ouch. B is not a descedant of A."); // проверяется runtime
  if (!is_base_of<A, D>::value)
    throw std::runtime_error("Ouch. D is not a descedant of A.");
}
А вот как сделать эту проверку compile-time -- без понятия.
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 16:58     Как сделать шаблон, с параметром-классом - потомком определённого класса? #10
в том то и дело , что
Цитата Сообщение от lemegeton Посмотреть сообщение
C++
1
if (!is_base_of<A, B>::value) // вычисляется compiletime
но вы же хотели
Цитата Сообщение от lemegeton Посмотреть сообщение
2. Это будет проверка времени выполнения, а не компиляции.
или я не так понял?

Добавлено через 2 минуты
чем вам для таких целей polymorphic_cast, например, не подойдет?
cyberguz
6 / 6 / 0
Регистрация: 01.12.2010
Сообщений: 105
19.01.2012, 17:06  [ТС]     Как сделать шаблон, с параметром-классом - потомком определённого класса? #11
Если вычисляется при компиляции - какой смысл проверять при выполнении? Чтобы позже обнаружить ошибку?
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 17:12     Как сделать шаблон, с параметром-классом - потомком определённого класса? #12
Цитата Сообщение от cyberguz Посмотреть сообщение
Если вычисляется при компиляции - какой смысл проверять при выполнении? Чтобы позже обнаружить ошибку?
абсолютно согласен
да и не возможно на этапе компиляции вычислить то что узнается на этапе выполнения, например, где-то после пяти минут работы после запуска проги
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.01.2012, 17:15     Как сделать шаблон, с параметром-классом - потомком определённого класса? #13
retmas, вычисляется compiletime, выполняется проверка runtime.

За polymorphic_cast не скажу, не пользовался.

Цитата Сообщение от cyberguz Посмотреть сообщение
Если вычисляется при компиляции - какой смысл проверять при выполнении? Чтобы позже обнаружить ошибку?
Например, чтобы вообще хоть когда-нибудь её обнаружить. )
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 17:45     Как сделать шаблон, с параметром-классом - потомком определённого класса? #14
Цитата Сообщение от lemegeton Посмотреть сообщение
Цитата Сообщение от cyberguz Посмотреть сообщение
Если вычисляется при компиляции - какой смысл проверять при выполнении? Чтобы позже обнаружить ошибку?
Например, чтобы вообще хоть когда-нибудь её обнаружить. )
зачем вам обнаруживать при выполнении то, что вычислено при компиляции, если это можно (и нужно) обнаружить при компиляции?

Добавлено через 17 минут
иными словами, зачем делать так
Цитата Сообщение от lemegeton Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdexcept>
 
template<typename Base, typename Derived>
struct is_base_of {
 private:
  static Derived* m_d;
  static char check( Base* );
  static long check( ... );
 public:
  enum {
    value = ( sizeof(check( m_d )) == sizeof(char) )
  };
};
 
class A {};
class B : public A {};
class D {};
 
int main(int argc, char *argv[]) {
  if (!is_base_of<A, B>::value) // вычисляется compiletime
    throw std::runtime_error("Ouch. B is not a descedant of A."); // проверяется runtime
  if (!is_base_of<A, D>::value)
    throw std::runtime_error("Ouch. D is not a descedant of A.");
}
А вот как сделать эту проверку compile-time -- без понятия.
если можно так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename Base, typename Derived>
struct is_base_of {
 private:
  static Derived* m_d;
  static char check( Base* );
  static long check( ... );
 public:
  enum {
    value = ( sizeof(check( m_d )) == sizeof(char) )
  };
};
 
class A {};
class B : public A {};
class D {};
 
int main(int argc, char *argv[]) {
  static_assert(std::is_base_of<A, B>::value, "Ouch. B is not a descedant of A.");
  static_assert(std::is_base_of<A, D>::value, "Ouch. D is not a descedant of A.");
}
Добавлено через 5 минут
Цитата Сообщение от lemegeton Посмотреть сообщение
Цитата Сообщение от Nick Alte Посмотреть сообщение
static_assert(std::is_base_of<Interface, InterfaceImplementation>::value, "Параметр должен быть потомком Interface");
1. Требуется новый стандарт или буст,
2. Это будет проверка времени выполнения, а не компиляции.
Цитата Сообщение от lemegeton Посмотреть сообщение
А вот как сделать эту проверку compile-time -- без понятия.
вот не пойму я: то вам нужна проверка времени выполнения, то compile-time... что вам нужно то вообще?
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
19.01.2012, 18:08     Как сделать шаблон, с параметром-классом - потомком определённого класса? #15
static_assert срабатывает во время компиляции, а не во время выполнения.
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
19.01.2012, 20:21     Как сделать шаблон, с параметром-классом - потомком определённого класса? #16
с этим никто и не спорит
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2012, 21:06     Как сделать шаблон, с параметром-классом - потомком определённого класса?
Еще ссылки по теме:

C++ Написать шаблон класса очередь, и сделать к типу char спецификацию
Шаблон класса, параметром которого должны являться наследники определённого класса C++
C++ Шаблон очереди с приоритетом и вложенным классом

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2012, 21:06     Как сделать шаблон, с параметром-классом - потомком определённого класса? #17
Есть еще альтернативный вариант написания такого хелпера. Раз у вас к хелперу такое требование, значит он вроде как расчитан на работу с интерфейсом IService, а не с конкретным
его имплементом. Это можно реализовать хранением смарт поинтера на IService внутри такого хелпера. Указатели на IService передаются хелперу извне при его создании (что есть хорошо, ибо отделяется место создания сервисов от места использования, меньшая связность компонент, уходит требование наличия у конкретного сервиса дефолтного конструктора) или же за счет вызова темплейтного конструктора. Сам хелпер при этом перестает быть шаблоном (что тоже хорошо. имплемент можно будет спрятать в спп файл последующие изменения в хелпере не будут влиять на другие файлы проекта). Требование о том, что передаваемый хелперу объект выполнится либо за счет строчки m_service(new Service()) (тупо не скомпилится, возможно с менее очевидным описанием ошибки компиляции, чем при статик ассертах), либо это декларится более явно в нешалбонном конструкторе хелпера.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class IService
{
public:
  virtual IService() {};
  // other methods
};
 
class ServiceHelper
{
public:
  template <class Service>
  ServiceHelper()
    : m_service(new Service())
  {
  }
 
  ServiceHelper(SmartPtr<IService> service)
    : m_service(service)
  {
  }
 
  // help methods
 
private:
  SmartPtr<IService> m_service;
};
Yandex
Объявления
19.01.2012, 21:06     Как сделать шаблон, с параметром-классом - потомком определённого класса?
Ответ Создать тему
Опции темы

Текущее время: 02:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru