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

Как сделать один шаблон для разных типов - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
ramybozy
8 / 8 / 0
Регистрация: 01.07.2012
Сообщений: 138
03.08.2012, 20:11     Как сделать один шаблон для разных типов #1
Предположим я реализую некоторый шаблонный класс, в котором, ну ради примера к объектам шаблонного типа (тип, используемый в заголовке шаблона <typename T>) используют операции сложения и вычитания.
Понятно, что если я создаю объекты типа objClasss<float> или objClasss<int>, то проблем нет.
Понятно, что проблем не будет, если в пользовательском классе (MyClass с последующим objClasss<MyClass> ), я реализую перегрузку операций сложения и вычитания.
Осталось выяснить, как все эти случаи умудриться засунуть в один шаблон.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
salam
157 / 138 / 11
Регистрация: 10.07.2012
Сообщений: 709
03.08.2012, 20:17     Как сделать один шаблон для разных типов #2
если в Вашем классе операторы действительно перегружены, то беспокоится не о чем...
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
03.08.2012, 20:42     Как сделать один шаблон для разных типов #3
Цитата Сообщение от ramybozy Посмотреть сообщение
Осталось выяснить, как все эти случаи умудриться засунуть в один шаблон.
Какие случаи? Здесь нет duck typing. Шаблоны раскрываются на этапе компиляции. Нет перегрузки — получаете сообщение об ошибке:
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
27
28
#include <iostream>
 
template <class T>
T foo(const T &x, const T &y)
{
  return x * y;
}
 
class Bar {
  int x;
public:
  Bar(int x_) : x(x_) {}
 
  friend
  std::ostream& operator<<(std::ostream &stream, const Bar &value);
};
 
std::ostream& operator<<(std::ostream &stream, const Bar &value)
{
  return stream << value.x;
}
 
int main(void)
{
  std::cout << foo(2, 3);
  std::cout << foo(Bar(2), Bar(3));
  return 0;
}
Код
prog.cpp: In function ‘T foo(const T&, const T&) [with T = Bar]’:
prog.cpp:26:   instantiated from here
prog.cpp:6: error: no match for ‘operator*’ in ‘x * y’
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
03.08.2012, 20:51     Как сделать один шаблон для разных типов #4
А где в этом коде оператор * для объектов типа Bar? что-то не увидел. поэтому и ошибка такая.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
03.08.2012, 20:56     Как сделать один шаблон для разных типов #5
А я о чём? Есть перегрузка — нет проблемы. Нет перегрузки — есть сообщение об ошибке. Что ещё надо-то?
По умолчанию создаются только конструкторы без аргументов и деструкторы. Если чего-то другого не будет найдено — получаем сообщение об ошибке ещё на стадии компиляции.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
03.08.2012, 20:58     Как сделать один шаблон для разных типов #6
ну да да. текст в начале сообщения я проглядел
ramybozy
8 / 8 / 0
Регистрация: 01.07.2012
Сообщений: 138
03.08.2012, 21:38  [ТС]     Как сделать один шаблон для разных типов #7
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Какие случаи? Здесь нет duck typing. Шаблоны раскрываются на этапе компиляции. Нет перегрузки — получаете сообщение об ошибке:
Что такое duck typing?
Не увидел у вас ответа на свой вопрос.
Грубо говоря, исходя из вашего кода, как действовать, когда T - это один из встроенных типов C++, и когда T - это пользовательский класс, исходя из того, что в обоих случаях мне нужно пользоваться операцией сложения. И разумеется в первом случае - это встроенная операция, а во втором случае - это перегрузка опекратора +.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
03.08.2012, 21:44     Как сделать один шаблон для разных типов #8
Цитата Сообщение от ramybozy Посмотреть сообщение
Не увидел у вас ответа на свой вопрос.
вот же и ответ
Цитата Сообщение от ramybozy Посмотреть сообщение
когда T - это один из встроенных типов C++, и когда T - это пользовательский класс, исходя из того, что в обоих случаях мне нужно пользоваться операцией сложения. И разумеется в первом случае - это встроенная операция, а во втором случае - это перегрузка опекратора +.
или в чем вопрос?
nameless
Эксперт C++
 Аватар для nameless
289 / 288 / 14
Регистрация: 16.06.2009
Сообщений: 486
03.08.2012, 21:52     Как сделать один шаблон для разных типов #9
Цитата Сообщение от ramybozy Посмотреть сообщение
Что такое duck typing?
разновидность динамической типизации, при которой принадлежность объекта к классу осуществляется путем проверки наличия всех свойств искомого класса в созданном объекте. Как то так..
ramybozy
8 / 8 / 0
Регистрация: 01.07.2012
Сообщений: 138
03.08.2012, 22:17  [ТС]     Как сделать один шаблон для разных типов #10
Цитата Сообщение от Jupiter Посмотреть сообщение
или в чем вопрос?
Ну мы значит разное имеем. Может быть я недостаточно точно объяснил, хорошо, зайдем тогда с другой стороны.
Реализовать класс, осуществляющий сортировку (неважно каким алгоритмом) так, чтобы этот класс можно было использовать и для объектов типа int, double, float и так далее, а также и для объектов пользовательских классов, например для структур student, в которых две структуры сраниваются на основе сранения значений их поля studentID, которое можно считать имеет тип int.

Единственное ограничение состоит в том, чтобы сделать это в рамках одного шаблонного класса, без дополнительных специализаций. Может быть так вообще сделать нельзя, тогда так и скажите.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
03.08.2012, 22:37     Как сделать один шаблон для разных типов #11
Ну определяете для классов метод с именем operator<символ оператора>. Для сравнения, например, так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int student::operator<(const student &other)
{
  int result;
  if (this->avg_mark == other.avg_mark) {
    result = 0;
  }
  else if (this->mark > other.avg_mark) {
    result = -1;
  }
  else {
    result = 1;
  }
  return result;
}
Всё, теперь мы можете сделать шаблонную функцию (или метод класса, не важно)
C++
1
2
3
4
5
6
7
template <class T>
void sort(std::vector<T> &vector)
{
  /* и в ней писать */
  if (vector[i] < vector[j]) {
  /* ... */
}
Для примитивных типов используется их встроенный operator<, для вашего student — определённый вами operator<.

В чём проблема? Не надо лепить каких-то отдельных специализаций для int с double отдельно, где использовать <, а для student отдельно, где использовать какой-нибудь compare. Определяйте operator< и пишите как обычно: a < b. Именно для этого и существует перегрузка операторов.

Пожалуйста, если этого будет недостаточно, оформите ваши мысли в виде кода, который вы бы хотели написать при реализации описанной функциональности. Типа: «Я хочу писать вот так: [...] и чтобы оно делало так-то и так-то. Это реально?»
ramybozy
8 / 8 / 0
Регистрация: 01.07.2012
Сообщений: 138
04.08.2012, 00:04  [ТС]     Как сделать один шаблон для разных типов #12
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Пожалуйста, если этого будет недостаточно, оформите ваши мысли в виде кода, который вы бы хотели написать при реализации описанной функциональности. Типа: «Я хочу писать вот так: [...] и чтобы оно делало так-то и так-то. Это реально?»
Пока нет, потому как такие вопросы возникают по ходу чтения учебников по программированию, которые, к сожалению в отличие от учебников по матану, страдают отсутствием строгости и полноты.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
04.08.2012, 00:48     Как сделать один шаблон для разных типов #13

Не по теме:

Простигосподи, вам рассказывали, что такое знаки препинания? Или это я тупой...


Так это, в чём проблема? Это конкретный вопрос. У вас есть задача. Её надо решить. Вы не знаете, как. Так?
Так что за задача, с которой возникла проблема? Сделать так, чтобы функция сортировки использовалась одинаково для всех типов:
C++
1
2
3
4
5
6
7
8
9
container<int> foo;
foo << 3 << 1 << 2;
sort(foo);
// foo: [1, 2, 3]
 
container<student> bar;
bar << student(1.2) << student(9.1) << student(-23.1);
sort(bar);
// bar: [{student: -23.1}, {student: 1.2}, {student: 9.1}]
И чтобы её код был сделан только один раз:
C++
1
2
3
4
5
6
7
template <class T>
void container<T>::sort()
{
  /* какой-то алгоритм сортировки, которому
     необходимо делать сравнения элементов
     типа T: container[i] <= container[j] */
}
То уже сказал же: перегрузите оператор сравнения (метод operator<=). Тогда container[i] <= container[j] будет работать и для встроенных типов, и для тех T, где оно перегружено.

Единственное ограничение состоит в том, чтобы сделать это в рамках одного шаблонного класса, без дополнительных специализаций. Может быть так вообще сделать нельзя, тогда так и скажите.
Вот я не понял вот этого. Что должно находиться в рамках одного класса? Чтобы внутри container<T> был прописан код для сравнения каких-нибудь student что ли?

Тогда да, это делается специализацией:
C++
1
2
3
4
5
6
7
8
template<>
class container<student> {
public:
  void sort();
  /* другие методы container */
}
 
void container<student>::sort() { /* ... */ }
Но другие методы тоже придётся реализовывать. К сожалению, при специализации нельзя переопределить какой-то один метод, а остальные унаследовать из общего шаблона (вообще, специализация может содержать совершенно другой набор методов, нежели общий шаблон <class T>). Возможно, это было вашей проблемой. Тогда ответ: нельзя.
ramybozy
8 / 8 / 0
Регистрация: 01.07.2012
Сообщений: 138
04.08.2012, 03:16  [ТС]     Как сделать один шаблон для разных типов #14
Вот теперь спасибо.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.08.2012, 13:38     Как сделать один шаблон для разных типов
Еще ссылки по теме:

Создать универсальный вектор для разных типов класса C++
Шаблон для пользовательских типов данных C++
Используя механизм перегрузки функции, вычислить для разных типов параметров C++

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

Или воспользуйтесь поиском по форуму:
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
04.08.2012, 13:38     Как сделать один шаблон для разных типов #15
Хотя в принципе, чисто технически можно сделать подобное исключение. С одной стороны, выглядит красиво, с другой — уродски. По объёму машинного кода выходит одинаково (я верю в dead code elimination).

sort пишется следующим образом (требует Boost; квест для продвинутых: написать свой велосипед с подобными свойствами):
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <boost/type_traits/is_same.hpp>
 
template <class T>
void container<T>::sort()
{
  if (boost::is_same<T, student>::value) {
    // вариант для student
  }
  else {
    // вариант для всего остального
  }
}
Вроде бы и элегантно, но действительно хотелось бы нормальное наследование.
Yandex
Объявления
04.08.2012, 13:38     Как сделать один шаблон для разных типов
Ответ Создать тему
Опции темы

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