Russian Qt Forum
Май 02, 2024, 01:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: (С++11) Variant - простой аналог boost::any  (Прочитано 37137 раз)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #15 : Февраль 13, 2015, 13:08 »

По поводу оператора ==, он однозначно нужен, чтобы можно было делать find. И его результат интерпретируется однозначно.

А вот по операторам сравнения не всё однозначно, я сейчас не могу вспомнить годный пример, помню только одно, что оно мне когда-то было нужно и я гуглил как это сделать с boost::any.. Может быть я тогда был не прав, не помню. Может быть стоит их выкинуть, чтобы никого не смущать?
« Последнее редактирование: Февраль 13, 2015, 13:17 от navrocky » Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Февраль 13, 2015, 14:25 »

По поводу оператора ==, он однозначно нужен, чтобы можно было делать find. И его результат интерпретируется однозначно.

А вот по операторам сравнения не всё однозначно, я сейчас не могу вспомнить годный пример, помню только одно, что оно мне когда-то было нужно и я гуглил как это сделать с boost::any.. Может быть я тогда был не прав, не помню. Может быть стоит их выкинуть, чтобы никого не смущать?
Тоже мне ценность "find". И насчет однозначности неясно (5 == 5.0  Непонимающий). Может неплохо бы иметь

bool isNumeric()
bool isPointer()
double toDouble()
void * toPointer()

А операторы/сортировки проще накрутить на стороне юзера
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #17 : Февраль 13, 2015, 16:59 »

Ну ладно, кому что.. Оставляю в том виде как есть, больше не наворачиваю.
Записан

Гугль в помощь
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #18 : Февраль 13, 2015, 18:25 »

Раз уж такое дело, приведу (чисто в академических целях) простенькую реализацию аналога boost::variant (не путать с boost::any)
Меташаблонная магия позволяет в этом случае полностью избавиться от RTTI, но взамен, при объявлении variantа нужно передать ему список тех типов с которыми он может работать, т.е:

Код
C++ (Qt)
variant<int, double, std::string> v = 10;
 
if (v.is_type<int>())
   std::cout << v.get<int>() << std::endl;
 
v = 0.5;
std::cout << v.get<double>() << std::endl;
 
v = std::string("hello-hello");
std::cout << v.get<std::string>() << std::endl;
 
 

« Последнее редактирование: Февраль 13, 2015, 18:26 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #19 : Февраль 13, 2015, 23:36 »

Раз уж такое дело, приведу (чисто в академических целях) простенькую реализацию аналога boost::variant (не путать с boost::any)
Меташаблонная магия позволяет в этом случае полностью избавиться от RTTI, но взамен, при объявлении variantа нужно передать ему список тех типов с которыми он может работать.

_id можно запихнуть в holder, всё же меньше копироваться будет )

Я так понимаю недопустимость типа тоже контролируется, т.е. запихнуть можно только тип из списка?

Можно назвать для большего понимания limited_variant или как-то так. Всё время меня смущало, что в бусте variant не variant в обычном понимании.
Записан

Гугль в помощь
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #20 : Февраль 14, 2015, 00:00 »

Цитировать
_id можно запихнуть в holder, всё же меньше копироваться будет )
Согласен)

Цитировать
Я так понимаю недопустимость типа тоже контролируется, т.е. запихнуть можно только тип из списка?
Да, тип только из доступных из списка. Это безопасно)

Цитировать
Можно назвать для большего понимания limited_variant или как-то так. Всё время меня смущало, что в бусте variant не variant в обычном понимании.
Можно, конечно.. Но я это уж так, не для пользования, а скорее ради обсуждения концепта) Т.е. если мне мне будет нужно, то я буду пользовать boost, конечно)

Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #21 : Февраль 14, 2015, 00:19 »

Цитировать
Но я это уж так, не для пользования, а скорее ради обсуждения концепта)
Кстатии, к слову о концепте)
Недавно здесь поднималась тема про свич и иже с ним, где я упомянул о static_visitor.. Так вот, в этой доморощенной реализации variant можно также реализовать нечто подобное визитёру.
Т.е. если у нас есть контейнер с вариантами и нужно его как то обработать без if-else-свичей то как вариант это можно сделать так:

Код
C++ (Qt)
#include <iostream>
#include <list>
#include <variant.h>
 
 
typedef variant<int, double, std::string> my_variant;
 
void print_int(const my_variant & v)
{
   std::cout << " int " << v.get<int>() << std::endl;
}
 
void print_double(const my_variant & v)
{
   std::cout << " double " << v.get<double>() << std::endl;
}
 
void print_str(const my_variant & v)
{
   std::cout << " str " << v.get<std::string>() << std::endl;
}
 
int main()
{
   std::list<my_variant> list;
   list.push_back(10);
   list.push_back(0.5);
   list.push_back(std::string("hello-hello"));
 
 
   variant_visitor<int, double, std::string> my_visitor;
 
   my_visitor.reg<int>(&print_int);
   my_visitor.reg<double>(&print_double);
   my_visitor.reg<std::string>(&print_str);
 
   for (auto v : list)
       my_visitor(v);
 
   return 0;
}
 
 
 

Код
Bash
int 10
double 0.5
str hello-hello
 


« Последнее редактирование: Февраль 14, 2015, 00:32 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Февраль 14, 2015, 09:47 »

Т.е. если у нас есть контейнер с вариантами и нужно его как то обработать без if-else-свичей то как вариант это можно сделать так:
Код
C++ (Qt)
   my_visitor.reg<int>(&print_int);
   my_visitor.reg<double>(&print_double);
   my_visitor.reg<std::string>(&print_str);
 
 
Ну switch все же куда приятнее чем N "псевдо-классов"  Улыбающийся

Эх, если бы это темплейт-усердие применить для реального дела, алгоритмов - вот было бы здорово! Но увы  Плачущий
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #23 : Февраль 14, 2015, 12:04 »

Эх, если бы это темплейт-усердие применить для реального дела, алгоритмов - вот было бы здорово! Но увы  Плачущий
Да, финдреплейсов можно было бы написать море, а сколько огромных свитчей можно было расширить на еще одно действие.... Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #24 : Февраль 14, 2015, 12:18 »

Эх, если бы это темплейт-усердие применить для реального дела, алгоритмов - вот было бы здорово! Но увы  Плачущий
Да, финдреплейсов можно было бы написать море, а сколько огромных свитчей можно было расширить на еще одно действие.... Улыбающийся


Непочатый край работы) Что ещё нужно для счастья творческой личности Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Февраль 14, 2015, 13:13 »

Ой-ой Улыбающийся Не, ну конечно так бы я не написал (не додумался бы), но вот чисто с утилитарной, прямо-таки "шкурной" точки зрения - а что, собственно, достигнуто? Еще одна остроумная поделка. А для чего? И как с нее снять бабло?..... Ну вот, сами же видите - никак. Может тлеет надежда "показать себя крутым" (чтобы больше платили) - так это напрасно  Улыбающийся

Ладно, тут у меня задумка мини-проект сделать и выложить, вот только немного освобожусь...
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #26 : Февраль 14, 2015, 13:16 »

Ой-ой Улыбающийся Не, ну конечно так бы я не написал (не додумался бы), но вот чисто с утилитарной, прямо-таки "шкурной" точки зрения - а что, собственно, достигнуто? Еще одна остроумная поделка. А для чего? И как с нее снять бабло?.....
А со свитча вы как бабло снимаете, а с фора? Улыбающийся

Может тлеет надежда "показать себя крутым" (чтобы больше платили) - так это напрасно  Улыбающийся
Ах эти комплексы. Улыбающийся
« Последнее редактирование: Февраль 14, 2015, 13:31 от Old » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #27 : Февраль 15, 2015, 13:52 »

 
Ой-ой Улыбающийся Не, ну конечно так бы я не написал (не додумался бы), но вот чисто с утилитарной, прямо-таки "шкурной" точки зрения - а что, собственно, достигнуто? Еще одна остроумная поделка. А для чего? И как с нее снять бабло?..... Ну вот, сами же видите - никак. Может тлеет надежда "показать себя крутым" (чтобы больше платили) - так это напрасно  Улыбающийся

Океюшки, вот простой типичный пример: Имеется контейнер вариантов, для различных представлений чисел, например (double, int, std::string).
Мы хотим иметь возможность сортировать его.. (самая типичная ситуация)
С патерном визитёра это делается в пару строк:
Код
C++ (Qt)
#include <iostream>
#include <list>
#include <variant.h>
#include <string>
 
 
typedef variant<int, double, std::string> variant_t;
 
int main()
{
   std::list<variant_t> list;
   list.push_back(std::string("-42.45938"));  // string
   list.push_back(0.5);                                  // double
   list.push_back(std::string("2.34"));         // string
   list.push_back(3.565);                            // double
   list.push_back(10);                                // int
 
 
   variant_visitor<double (variant_t)> my_visitor;
 
   my_visitor.reg<int>([](variant_t v) { return v.get<int>(); } );
   my_visitor.reg<double>([](variant_t v) { return v.get<double>(); } );
   my_visitor.reg<std::string>([](variant_t v) { return std::stod(v.get<std::string>()); } );
 
   for (auto v : list)
       std::cout << my_visitor(v) << std::endl;
 
   list.sort([&](variant_t v1, variant_t v2) { return my_visitor(v1) > my_visitor(v2); });
 
   std::cout << "--------------------------------" << std::endl;
 
   for (auto v : list)
       std::cout << my_visitor(v) << std::endl;
 
 
   return 0;
}
 

Причём, мы имеем полную типобезопасность)

Мне вот интересно, как Вы аналогичное будете реализовывать с Вашим милым и родным свитчем? 

P.S. Проект приаттачен..

PPS Надеюсь, комрад  navrovsky с пониманием отнесётся к тому, что мы тут паразитируем на его теме)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Февраль 15, 2015, 15:04 »

Причём, мы имеем полную типобезопасность)
"типо" может и имеете, но вот ошибки не контролируете, напр string("abc")

Мне вот интересно, как Вы аналогичное будете реализовывать с Вашим милым и родным свитчем? 
Да хотя бы так
Код
C++ (Qt)
bool IsLess( const Variant & v1, const Variant & v2 )
{
double d1, d2;
bool num1 = TryConvert2Double(v1, &d1);
bool num2 = TryConvert2Double(v2, &d2);
if (num1 && num2)
 return d1 < d2;
return num1 && !num2;
}
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #29 : Февраль 15, 2015, 15:15 »

Цитировать
"типо" может и имеете, но вот ошибки не контролируете, напр string("abc")
Для иллюстрации данного примера это не принципиально..


Цитировать
Да хотя бы так
Чтож Вы самое интересное то не показали?
Можно под капот TryConvert2Double посмотреть?)


Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.159 секунд. Запросов: 22.