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

шаблон для некоторых классов - C++

Восстановить пароль Регистрация
 
Riderik
 Аватар для Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
29.12.2012, 16:23     шаблон для некоторых классов #1
идея, скорее всего, бредовая, но всё же уточнить нужно, вдруг так можно. У меня возникла такая ситуация: есть две идентичные функции. Единственное различие между ними это тип списка, передаваемого в них, и тип объекта, который объявляется в этих функциях (по типу списка). Так вот, можно ли объединить эти две функции в такую функцию, которая принимает только один из этих типов и никакой другой (оба типа унаследованы от одного базового класса и в функции нужно вызывать виртуальную функцию).

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
class Base {
public:
    virtual void f() {};
};
 
class Der :  public Base {
public:
    void f() {}
};
 
class Der2 : public Base {
public:
    void f() {}
};
 
 
void funk(std::list<Der>& l) {
    Der a;
    a.f();
    l.push_back(a);
}
 
void funk(std::list<Der2>& l) {
    Der2 a;
    a.f();
    l.push_back(a);
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
29.12.2012, 16:25     шаблон для некоторых классов #2
Riderik,
C++
1
std::list<Base*>
?
Riderik
 Аватар для Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
29.12.2012, 16:27  [ТС]     шаблон для некоторых классов #3
ForEveR, выбьет ошибку, что нельзя преобразовать один тип листа к другому
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,579
Записей в блоге: 17
29.12.2012, 16:27     шаблон для некоторых классов #4
C++
1
2
3
4
5
6
7
template<T>
void funk(std::list<T>& l) 
{
    T a;
    a.f();
    l.push_back(a);
}
В чем проблема ?
Riderik
 Аватар для Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
29.12.2012, 16:29  [ТС]     шаблон для некоторых классов #5
Avazart, ну это да, но сюда же можно передать любой тип, у которого найдется функция f. А вот можно ли передать только что-то из определенной иерархии?
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
29.12.2012, 16:31     шаблон для некоторых классов #6
А то, что вариант, предложенный ForEver'ом, не рабочий, это было установлено опытным путем или предпололжение? Потому что это как раз то, что тебе нужно.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
29.12.2012, 16:34     шаблон для некоторых классов #7
Riderik, Ну как бэ.

C++
1
2
3
4
5
6
7
8
9
typedef std::list<std::shared_ptr<Base>> bases_t;
 
template<typename T>
void f(bases_t& l)
{
   std::shared_ptr<Base> p(new T());
   p->foo();
   l.push_back(p);
}
Подавать в функцию естественно список с указателями на Base. Или std::enable_if использовать.
Riderik
 Аватар для Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
29.12.2012, 16:36  [ТС]     шаблон для некоторых классов #8
Kastaneda, написал так:
C++
1
2
3
4
5
6
7
8
void funk(std::list<Base*>& l) {
}
 
int main() {
    std::list<Der*> l;
    funk(l);
    return 0;
}
Выбило ошибку
невозможно преобразовать параметр 1 из "std::list<_Ty>" в "std::list<_Ty> &"
не удается инициализировать ссылку типа "std::list<Base *, std::allocator<Base *>> &" (квалифицируется как неконстантная) со значением типа "std::list<Der *, std::allocator<Der *>>"

Добавлено через 1 минуту
ForEveR, а это хорошая мысль
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
29.12.2012, 16:42     шаблон для некоторых классов #9
Думаю имлось ввиду сделать так
C++
1
2
std::list<Base*> l;
funk(l);
а список уже заполнять указателями на Der или Der2.
Но там потом возникла бы заморочка с создаванием объекта нужного типа, так что да, возможно и не самый удобный вариант.
Riderik
 Аватар для Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
29.12.2012, 16:47  [ТС]     шаблон для некоторых классов #10
А стоп. У меня есть два списка: list<Der> и list<Der2> (ну или списки на их указатели). Они необходимы, так как используются методы из Der и Der2. И там же один из списков нужно отправить в эту функцию. Так можно сделать?

Добавлено через 3 минуты
Типа этого:
C++
1
2
3
4
5
6
7
int main() {
    std::list<Der> l;
    std::list<Der2> l2;
    funk(l);
    funk(l2);
    return 0;
}
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,579
Записей в блоге: 17
29.12.2012, 16:48     шаблон для некоторых классов #11
На мой взгляд перегрузка единственный оптимальный вариант в данном случае
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
29.12.2012, 16:51     шаблон для некоторых классов #12
Можно. Но придется слегка поколебаться.

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 <type_traits>
#include <list>
 
class Base
{
};
 
class Der : public Base
{
};
 
template<typename T>
void f(T&, typename std::enable_if<!std::is_base_of<Base, typename T::value_type>::value>::type** = 0);
 
template<typename T>
void f(T&, typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value>::type** = 0)
{
}
 
int main()
{
    std::list<Der> ders;
    f(ders);
}
ну или просто static_assert влепить, если std::is_base_of<>::value вернет false.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,579
Записей в блоге: 17
29.12.2012, 16:59     шаблон для некоторых классов #13
Цитата Сообщение от ForEveR Посмотреть сообщение
C++
1
2
3
4
5
6
7
template<typename T>
void f(T&, typename std::enable_if<!std::is_base_of<Base, typename T::value_type>::value>::type** = 0);
 
template<typename T>
void f(T&, typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value>::type** = 0)
{
}
А зачем дублировать ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.12.2012, 17:07     шаблон для некоторых классов
Еще ссылки по теме:

C++ Шаблон классов
Иерархия классов + шаблон C++
C++ Шаблон для односвязного списка

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
29.12.2012, 17:07     шаблон для некоторых классов #14
Avazart, Дублировать? В одном случае работает, если не base_of, во втором, если base_of.

Добавлено через 1 минуту
Avazart, В сущности конечно можно оставить одну функцию. Тогда ошибка будет не undefined reference, а даже нечто более понятное.

Добавлено через 3 минуты
Хотя в данном случае наверное интереснее будет так.

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
29
30
#include <type_traits>
#include <list>
 
class Base
{
};
 
class Der : public Base
{
};
 
template<typename T>
void f_impl(std::list<T>&, std::false_type);
 
template<typename T>
void f_impl(std::list<T>&, std::true_type)
{
}
 
template<typename T>
void f(std::list<T>& lst)
{
    f_impl(lst, std::is_base_of<Base, T>::type());
}
 
int main()
{
    std::list<Der> ders;
    f(ders);
}
Yandex
Объявления
29.12.2012, 17:07     шаблон для некоторых классов
Ответ Создать тему
Опции темы

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