Форум программистов, компьютерный форум, киберфорум
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. Показов 1933. Ответов 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru