Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/25: Рейтинг темы: голосов - 25, средняя оценка - 4.60
 Аватар для Prostoplus
12 / 2 / 1
Регистрация: 21.09.2012
Сообщений: 122

Обобщенный указатель на шаблонный класс

01.03.2015, 13:59. Показов 4953. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Имеется класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <typename T>
class TListManager
{
protected:
    TList <T> *head;
    TList <T> *tail;
public:
    TListManager():head(NULL),tail(NULL){}
    void add(T _obj);
    T get();
    friend ostream& operator<<(ostream &strm, TListManager lm);
    TList<T>* getBegin()const {return head;}
    TList<T>* getTail() const {return tail;}
    unsigned getSize();
    void erase();
};
Можно ли создать обобщенный указатель на него? Например:
C++
1
2
3
4
5
6
7
8
9
TListManager *lm;
switch(rand()%2)
{
case 0: lm = new TListManager<float>();
break;
case 1: lm = new TListManager<int>();
break;
}
lm->add(333);
Или как-то "емулировать" это? Например, создать класс - адаптер или базовый для класса TListManager суперкласс, а дальше использовать указатель на него? И сделать так, что бы при обращении к методу через такой "универсальный" указатель не нужно было его приводить к конкретному типу.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.03.2015, 13:59
Ответы с готовыми решениями:

Указатель на шаблонный класс
Есть ли возможность инициализировать указатель на класс с шаблоном, но не указав при этом тип, ну т.е. написать не так Value_Class...

Указатель на абстрактный шаблонный класс
Есть абстрактный шаблон класса и 3 производных от него шаблонов классов. Так же есть шаблонная функция, в которую нужно передать указатель...

Обобщенный указатель типа void
В приложенной картинке рассказывается о динамическом распределении памяти в С. Сказано, что функция malloc() возвращает указатель типа...

25
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
02.03.2015, 13:29
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
мне любопытно, как вы сможете эмулировать пачку универсальных аргументов ака boost::any, с помощью туплей или структурки.
Пачку универсальных независимых аргументов - никак. А если просто пачку аргументов, то как-нибудь так:
C++
1
2
3
4
5
If( ... )  {
    boost::any_cast<std::tuple<int, std::string, foobar>&>( ... );
} else {
    boost::any_cast<std::tuple<float, char, barbaz> & >( ... );
}
Ну, в общем думаю идея ясна. Аналогично можно кастить в разны структурки.

Цитата Сообщение от hoggy Посмотреть сообщение
довольно странная реакция, учитывая, что обсуждаются задачи
Обсуждать сферических коней в вакууме порой бывает интересно, только не стоит забывать, что на практике
такие вещи вряд-ли найдут свое применение ( предложишь пример, где тебе пригодится функция в 2-умя или более boost::any ? )

Цитата Сообщение от hoggy Посмотреть сообщение
безопасно передавать аргументы любых типов посредством полиморфного интерфейса.
Ну, кхм, в моем понимаии 'безопасно' и 'приведения типов в рантайм' это взаимоисключающие понятия
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
02.03.2015, 15:39
Цитата Сообщение от Voivoid Посмотреть сообщение
Ну, в общем думаю идея ясна. Аналогично можно кастить в разны структурки.
Можно создать тупель, который заряжается ссылками на аргументы,
а в boost::any закладывается ссылка на сам тупель.
Все это можно обыграть в компал-тайме.

Спасибо.

Я думал о таком.
Пожалуй, это было первое, о чем я подумал, когда велосипедировал свои делегаты.
Но я тогда не осилил одну инженерную задачу (об этом ниже),
поэтому, отказался от этой идеи.


Цитата Сообщение от Voivoid Посмотреть сообщение
предложишь пример, где тебе пригодится функция в 2-умя или более boost::any ?
Могу предложить парочку примеров где использовал динамику.

1. Динамический делегат.

статический выглядит так:
C++
1
2
3
4
std::function<int (int)> 
    call1 = foo;
std::function<int (int,int)>
    call2 = bar;
динамический выглядит так:
C++
1
2
Connector call1 = foo;
Connector call2 = bar;
Последний вариант отличается от первого тем, что он - не шаблонный.
Это очень удобно, когда хочется хранить экземпляры в одном массиве, например.

Но главная его отличие от статических аналогов (собственно, ради этого я его и создавал):
его можно легко нацеливать на функции, типы которых могут быть известны только в рантайме.

Вот пример реальной задачи:

Кликните здесь для просмотра всего текста
Нужно забиндить методы любого класса, и вызывать их используя символьные имена.
При этом в задаче было требование: аргументы передаются нативно:
(хотя это не принципиально, при желании, можно и аргументы обыграть символьно,
правда для этого придется задействовать уже другой, ещё один динамический механихзм - variant)

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
31
struct Some
{
    int Work()                { std::cout<<"work\n";  return 0; }  
    void Test(int a)          { std::cout<<"Test(a)\n";      }
    void Bar(int a1, int a2){ std::cout<<"Bar(a1,a2)\n"; }
};
 
#define LINK(obj,func) \
    RegisterMethod(#func, Den::Connector(obj, &decltype(obj)::func) );
 
int main()
{
    //использование
 
    //для объекта некоторого класса
    Some obj;
 
    //регистрируем методы. Указывать нужно только имя метода. 
    //Точный тип указателя на фунцию-метод будет вычислен автоматически
    LINK(obj, Work); 
    LINK(obj, Test); 
    LINK(obj, Bar);
 
    //теперь методы можно вызывать с помощью символьного имени:
 
    int result = Invoke(obj,"Work");       
 
    Invoke(obj,"Test",10);    
 
    Invoke(obj,"Bar",10,10); 
}

Что бы обыграть нечто подобное с помощью статического делегата,
придется решить ряд инженерных задач:

1. Как хранить разные инстансы шаблона в одном контейнере?

2. Как передавать аргументы?
Учитывая, что времени компиляции не известно, с какими типами будет запущен какой делегат.

3. Как получать результат?

Единственное решение, которое я видел с использованием статического делегата
в итоге все сводило к виду:
C++
1
std::function<boost::any(boost::any)>
Причем, там под капотом такой ужас открывался на шаблонах:
формировался вектор из boost::any.

Смысл в том, что существуют задачи, которые нельзя решить только в статике.
И тогда любое возможное решение в любом случае будет сведено к динамике.

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

За динамику приходится платить.
Мой Arg в релизе сворачивался в обычный void*.
Никаких аллокаций, никаких проверок. По идее получается статика.
Но тем не менее, догнать по скорости статические аналоги мне так и не удалось.

======================================== ==============

Другая задача: вариантивный тип:

Умеет формировать динамические структуры любой сложности.
Умеет принимать объекты любых типов (упраздняет any)
Умеет хранить по ссылкам/значению(упраздняет arg)

C++
1
2
3
4
5
6
7
8
9
10
std::vector<int> vec(10,10);
 
variant v;
v[0]["hello"]  = vec;
v[1]["world"] = true;
v[2].ref(vec);
 
const auto& re = v[10]["hello"];
 
std::cout<< v<<std::endl;
Для варианта динамика - это все.



А теперь по поводу туплей.

С ними есть проблема.

Рассмотрим два тупля:

std::tuple<int, some&>
и
std::tuple<int, const some&>

Это два принципиально различных типа тупля.


Однако, отправитель имеет полное право отправить int&,
а получатель имеет полное право забирать, как const int&

Потому что в этом случае квалификатор не нарушается, и преобразование безопасно.

Ну и как тогда чекать такие тупли???


http://rextester.com/CCKAPJ5357

Кликните здесь для просмотра всего текста
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
31
32
33
34
35
36
37
38
39
40
41
42
//Title of this code
//g++  4.8.2
 
#include <iostream>
#include <boost/any.hpp>
#include <tuple>
 
 
 
void test(boost::any a )
{
    typedef std::tuple<int, const int&>
        type;
 
    try{
        const auto mytuple = boost::any_cast<type>(a);
        std::cout<<"a1 = "<< std::get<0>(mytuple);
        std::cout<<"a2 = "<< std::get<1>(mytuple);
    }
    catch(const std::exception& e)
    {
        std::cout<<"ERROR: INVALID TYPE\n";
        std::cout<< e.what() << std::endl;
    }
}
 
 
template<class A1, class A2> void send(A1&& a1, A2&& a2)
{
    boost::any a = std::make_tuple(a1,a2);
    test(a);
}
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    int v = 10;
    int& r = v;
    send(10, r);
}
Hello, world!
ERROR: INVALID TYPE
boost::bad_any_cast: failed conversion using boost::any_cast



Мой Arg умеет проверку типов и квалификаторов.
Кроме того он умеет некоторые типичные приведения типов.
Кроме этого, можно например, отправить массив, а получать по указателю.
Потому что на языке с++ массив имеет право неявно каститься к указателю.

Кроме того есть возможность настраивать политики безопасности.
Если сделать не строгую, то можно будет отправлять int,
а получать float (потерь данных нет - почему бы и нет?)
И тд, и тп.

А вот для тупля я в своё время такое не осилил (но я тогда и язык то ещё не очень хорошо знал).

Сегодня я могу реализовать оптимизацию на туплях.
Но для этого придется задействовать type erasure, и мало-мало пошаманить.

Добавлено через 2 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
Ну, кхм, в моем понимаии 'безопасно' и 'приведения типов в рантайм' это взаимоисключающие понятия
Некоторые задачи предполагают работу с типами в динамике.
И в этой ситуации ваше понимание становится не очень то интересным.
Потому что решить такие задачи оно уже не поможет.
1
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
02.03.2015, 18:02
Цитата Сообщение от hoggy Посмотреть сообщение
Ну и как тогда чекать такие тупли???
Ну, первое что пришло в голову сделать вот такой вот ход конем: создавать туплы boost::variant'ов.
т.е. что-то типа std::tuple<boost::variant<int, int&, const int&>, boost::variant<foobar, foobar&, const foobar&>>
Потом все это дело диспатчить в визиторах и по одному аргументу биндить в функтор. Вроде на первый взгляд должно помочь. Может если время будет, попробую прототипчик набросать

Добавлено через 33 минуты
А туплу скрываем за boost::any, потом, во время вызова функции кастим any к тупле, типы для которой берем из типов аргументов функции
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
02.03.2015, 18:03
Цитата Сообщение от Voivoid Посмотреть сообщение
Ну, первое что пришло в голову сделать вот такой вот ход конем: создавать туплы boost::variant'ов.
т.е. что-то типа std::tuple<boost::variant<int, int&, const int&>, boost::variant<foobar, foobar&, const foobar&>>
Потом все это дело диспатчить в визиторах и по одному аргументу биндить в функтор. Вроде на первый взгляд должно помочь. Может если время будет, попробую прототипчик набросать
Идею понял.
Может быть даже и взлетит.
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
25.02.2017, 00:22
hoggy, а если так:
C++
1
2
template<class T>
using ptr_to_class = TListManager<T>*;
или через смарт:

C++
1
2
template<class T>
using ptr_to_class = std::shared_ptr<TListManager<T>>;
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.02.2017, 14:07
Цитата Сообщение от zarko97 Посмотреть сообщение
а если так
не понятно, к чему это было
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.02.2017, 14:07

Класс Matrix: реализовать шаблонный класс для двумерных массивов
Доброго времени суток. У меня вопрос: я создал класс Array со внутренним динамическим массивом и объекты этого типа смог создать и я ими...

Обобщенный и не обобщенный класс с одинаковым именем
Добрый день! Task&lt;int&gt; task = Task.Run(() =&gt; { Console.WriteLine(&quot;Foo&quot;); return 3; }); Как такое возможно? Метод Run Возвращает тип...

Обобщенный класс
Задание: Создать обобщенный класс для хранения объектов-исключений. Тип исключения задается при построении класса. Перекрыть в создаваемом...

Обобщенный класс
Здравствуйте, есть такая задача: Создать обобщенный класс для хранения произвольных данных в массиве. Реализовать функцию добавления...

обобщенный класс для чисел
Всем привет. Написал тип numb для целых и дробных чисел, но не смог написать перегрузку оператора &lt;&lt; для вывода через cout. Вот что...


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

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Новые блоги и статьи
Remote Connection Manager
DevAlt 21.06.2026
Написал для себя небольшую прилагу: https:/ / github. com/ altbodhi/ ReConMan По итогу пришел к мысли, что DU не дружат с существующими технологиями. От сериализации до отображения в реляционную. . .
Администрация Хабра удаляет новые энрегоэфективные алгоритмы, которые не западной школы кода, и вовсе никак не сгенерировавны.
Hrethgir 20.06.2026
Делается это, как замечено, при правках - при объявлении концептуальных отличий в алгоримах. Делается это, по линейке событий - после дополнения публикации основными отличиями от основных западных. . .
Процесс ориентированная диалектика (не новость - просто системное обновление, философия).
Hrethgir 20.06.2026
Однажды один участник в своём блоге, на этом форуме, сделал запись "О языках замолвите слово". Понимая, что язык - важная вещь, я решил хорошо подумать, прежде чем сказать, и сказал то, что вы видите. . .
Контроль уникальности строк в табличной части документа
Maks 18.06.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ПланированиеСпецтехники" с табличной частью "НаличиеОборудования", разработанного в КА2. Задача: контроль уникальности строк в. . .
Клиент
Uhbif79 18.06.2026
Здесь простой клиент для работы с сервером.
Сервер
Uhbif79 18.06.2026
Выкладываю простейший сервер.
Дефенестрация
kumehtar 18.06.2026
Узнал интересное слово. Дефенестрация. Это когда ты выбрасываешь кого-либо или что-либо из окна. Возьму на вооружение)))
Дихотомия добра и зла
kumehtar 18.06.2026
Как Дзен-буддисты говорят о добре и зле: не нужно воевать против зла, нужно воевать против невежества. Тогда добро станет ествественным, и поэтому вечным. Но дело в том, что невежество всё время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru