Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112

Boost::any and std::function

01.08.2014, 14:25. Показов 1916. Ответов 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
25
26
27
28
#include <iostream>
#include <typeinfo>
#include <functional>
#include <boost/any.hpp>
 
struct Foo
{
    void bar()
    {
        std::cout << "foobar" << std::endl;
    }
};
 
void to_any(const boost::any& any)
{
    std::cout << any.type().name() << std::endl;
}
 
int main()
{
    Foo fb;
    std::function<void()> f = std::bind(&Foo::bar, &fb);
 
    to_any(f);
    to_any(std::bind(&Foo::bar, &fb));
 
    return 0;
}
Почему разные типы и как сделать так чтобы типы были одинаковые?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.08.2014, 14:25
Ответы с готовыми решениями:

Подключение boost как std
Возможно ли подключить boost как std? Ну например, чтоб это: #include &lt;iostream&gt; #include &lt;string&gt; #include...

Boost::serialization, как сериализовать std::tuple?
В принципе вопрос в теме. Как именно?

boost serialization. загрузка данных из архива в std::list
День добрый, возникла небольшая проблема. Я сохраняю данные в архив используя #include&lt;boost/serialization/list.hpp&gt; ...

12
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
01.08.2014, 15:38
stima, Потому что результат возвращаемый bind не является std::function, но std::function может быть сконструирован от результата bind-а. Соответственно либо сконвертировать в std::function, либо использовать auto.

C++
1
auto f = std::bind(&Foo::bar, &fb));
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
01.08.2014, 15:46  [ТС]
Сори забыл упамянуть, нужно это сделать без дополнительной конвертации в std::function/auto

Добавлено через 2 минуты
Возможно ли заврапить std::function во что-то другое?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
01.08.2014, 16:11
stima, Нужно результат от bind-а заврапить и function во что-нибудь другое. Нужна более конкретная постановка задачи.
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
01.08.2014, 16:32  [ТС]
Вообще хочу реализовать MetaObject. Как-то так. Советы принимаются с удовольствием.

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <typeinfo>
#include <functional>
 
#include <unordered_map>
#include <boost/any.hpp>
 
 
class MetaObject
{
 
public:
    MetaObject()
    {
    }
 
    void connect(const std::string& name, const boost::any& any)
    {
        mapped_any.insert(std::make_pair(name, any));
    }
 
    //упрощенныей вариант
    void invoke(const std::string& method)
    {
         boost::any& any = mapped_any[method];
         std::function<void()>& f = boost::any_cast<std::function<void()>&>(any);
         f();
    }
 
private:
    std::unordered_map<std::string, boost::any> mapped_any;
};
 
class Foo : public MetaObject
{
public:
    Foo() : MetaObject()
    {
        //это не совсем красиво
        std::function<void()> f = std::bind(&Foo::bar, this);
        connect("bar", f);
 
        //хочется так
        connect("bar", std::bind(&Foo::bar, this));
    }
 
    void bar()
    {
        std::cout << "foobar" << std::endl;
    }
};
 
int main()
{
    Foo fb;
    MetaObject *mo = &fb;
 
    mo->invoke("bar");
 
    return 0;
}
Добавлено через 2 минуты
п.с. Qt не предлагать)
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
01.08.2014, 16:53
stima, Вай нот template?

C++
1
2
3
4
5
    template<typename T>
    void connect(const std::string& name, const T& function)
    {
        mapped_any.insert(std::make_pair(name, function));
    }
Но при этом, фиг его знает что там вернет bind. Собственно...

И да, почему обязательно boost::any? Что мешает хранить прям function?
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
01.08.2014, 17:04  [ТС]
На саммом деле

C++
1
2
connect<boost::any>("name", boost::bind(&Foo::bar, this));
connect<std::function<void()>>("name", boost::bind(&Foo::bar, this));
Даст тоже разный результат. А первое хочется запретить.

Добавлено через 6 минут
Ок запретить можно впринципе через спецификацию шаболна.

C++
1
2
3
4
5
template<>
connect<boost::any>(const std::string&, const boost::any&)
{
static_assert(false, "");
}
п.с. А Как хранить функции разных типов? Через void*?
0
28 / 23 / 12
Регистрация: 25.08.2013
Сообщений: 44
03.08.2014, 14:40
stima, из примера не понятно, зачем тут нужен boost::any. Если сигнатура не меняется, то std::function будет достаточно.

Такой вариант подойдет ?

C++ (Qt)
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <typeinfo>
#include <functional>
 
#include <unordered_map>
//#include <boost/any.hpp>
 
 
class MetaObject
{
 
public:
  MetaObject()
  {
  }
 
  void connect( const std::string & name, const std::function<void()> & fun )
  {
    _mapped_fun.emplace( name, fun );
  }
 
  void invoke( const std::string & method ) const
  {
    auto fun = _mapped_fun.find( method );
    if ( fun != _mapped_fun.end() )
      (*fun).second ();
  }
 
private:
  std::unordered_map<std::string, std::function<void()>> _mapped_fun;
};
 
class Foo : public MetaObject
{
public:
  Foo() : MetaObject()
  {
    connect( "bar", std::bind(&Foo::bar, this) );
    connect( "foo", [this] {foo();} );
  }
 
  void bar()
  {
    std::cout << "foobar" << std::endl;
  }
 
    void foo()
  {
    std::cout << "barfoo" << std::endl;
  }
};
 
int main()
{
  Foo fb;
  MetaObject * mo = &fb;
 
  mo->invoke( "bar" );
  mo->invoke( "foo" );
  mo->invoke( "lol" );
 
  return 0;
}
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
03.08.2014, 15:51  [ТС]
Сигнатура меняется. Такой вариант не подойдет.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.08.2014, 19:26
stima, В таком случае как ты работаешь с any? Если сигнатура не одна, значит нужен свитч или что-то вроде. Хотелось бы РЕАЛЬНЫЙ вариант кода.
0
28 / 23 / 12
Регистрация: 25.08.2013
Сообщений: 44
03.08.2014, 22:28
Цитата Сообщение от stima Посмотреть сообщение
Сигнатура меняется. Такой вариант не подойдет.
Тогда так. Правда только для лямбд, т.к. bind возвращает объект с шаблонными параметрами, поэтому по-простому не получится.

Идея в том, что у функтора берется сигнатура, которая используется для создания оболочки в виде std::function. При вызове пытаемся собрать изначальный тип и в случае успеха вызвать функцию.

C++ (Qt)
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <functional>
#include <typeinfo>
#include <unordered_map>
#include <boost/any.hpp>
 
template<typename _Func>
struct fun_signature_t;
 
template<typename _Ret, typename ..._Args>
struct fun_signature_t<_Ret(*)(_Args...)>
{
  using type = std::function<void(_Args...)>;
};
 
template<typename _Class, typename _Ret, typename ..._Args>
struct fun_signature_t<_Ret(_Class::*)(_Args...)>
{
  using type = std::function<void(_Args...)>;
};
 
template<typename _Class, typename _Ret, typename ..._Args>
struct fun_signature_t<_Ret(_Class::*)(_Args...) const>
{
  using type = std::function<void(_Args...)>;
};
 
 
struct fun_signature
{
  template <typename _Obj, typename _Type = decltype(& _Obj::operator()) >
  static auto get_signature( _Obj &, _Type = nullptr ) -> _Type;
 
  template< typename _Obj, typename _Type = _Obj * >
  static auto get_signature( _Obj * = {} ) -> _Type;
};
 
 
 
 
class MetaObject
{
 
public:
  MetaObject()
  {
  }
 
  template<typename _FObj , typename ..._Args>
  void connect( const std::string & name, const _FObj & fun )
  {
    using f_type = decltype( fun_signature::get_signature(fun) );
    using func = typename fun_signature_t<f_type>::type;
 
    _mapped_fun.emplace( name, func(fun) );
  }
 
  template<typename ..._Args>
  void invoke( const std::string & method, _Args ... args )
  {
    auto fun_any = _mapped_fun[method];
    if ( !fun_any.empty() )
    {
      using signature = std::function<void( _Args... )>;
      if ( fun_any.type() == typeid(signature) )
      {
        auto func = boost::any_cast< signature >( fun_any );
        func( args... );
      }
      else 
      {
        std::cout << "wrong sign: " <<  typeid(signature).name() << "\nexpected : " << fun_any.type().name() << std::endl;
      }
    }
  }
 
private:
  std::unordered_map< std::string, boost::any > _mapped_fun;
};
 
class Foo : public MetaObject
{
public:
  Foo() : MetaObject()
  {
    connect( "foo", [this] {foo();} );
    connect( "bar", [this] (int val) {bar(val);} );
  }
 
  void bar( int val )
  {
    std::cout << "foobar: " << val << std::endl;
  }
 
    void foo()
  {
    std::cout << "barfoo" << std::endl;
  }
};
 
int main()
{
  Foo fb;
  MetaObject * mo = &fb;
 
  mo->invoke( "bar", 100500 );
  mo->invoke( "bar", 10, 42, 51 );
  mo->invoke( "foo" );
 
  return 0;
}
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
03.08.2014, 23:27  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
Если сигнатура не одна, значит нужен свитч или что-то вроде.
Да, что то наподобие

Цитата Сообщение от ForEveR Посмотреть сообщение
Хотелось бы РЕАЛЬНЫЙ вариант кода.
Зачем?)

Добавлено через 5 минут
п.с.

Вообще boost::any был взят чтобы не через void*

2StailGot такой варинат тоже не подойдет. Целью является запретить все методы кроме методов Derived класса.

Если честно перед тем как задать вопрос я знал ответ, просто ожидал, что кто-то уже реализовывал такую штуку, может подсказал бы свой вариант реализации.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.08.2014, 10:14
stima, Понятное дело, почему был использован boost::any. Если решили задачу просьба поделится на каком-нибудь простом примере, вдруг кому пригодится.

Добавлено через 5 минут
П.С. вариант от товарища StailGot как раз и запрещает вызов всех функций, кроме наследника. Можно просто заменить вывод в лог на throw (это конечно не этап компиляции, но все же).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.08.2014, 10:14
Помогаю со студенческими работами здесь

Отличие std::auto_ptr<SomeType> от boost::shared_ptr<SomType>
Господа программисты, хочу задать вам вопрос: чем умный указатель std::auto_ptr&lt;SomeType&gt; отличается от бустового умного указателя...

Чем boost::signal отличается от std::function
Чем boost::signal отличается от std::function ?

Какая реализация лучше? std::pointer_to_binary_function vs std::function
Какая реализация (set_p или set_f) лучше /современнее / эффективнее ? pointer_to_binary_function в С++11 объявлен как deprecated. Правильно...

Использование std::function в std::thread
Нужно вызвать function fnc в новом потоке. Как сделать? function &lt;void(vector&lt;char&gt;)&gt; fnc; void test(vector&lt;char&gt; data) { ...

Class member function to std::function
Всем привет. Вопрос: почему 43 строка не работает? #include &lt;functional&gt; #include &lt;iostream&gt; template &lt;typename C,...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru