Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
1

Вызов const метод std::function

01.12.2015, 12:58. Показов 2036. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день,

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
#include <functional>
#include <string>
#include <iostream>
using namespace std;
 
class Foo
{
public:
    std::string getValue(double, int, std::string) const
    {
        cout << "const" << endl;
        return "";
    }
    std::string getValue(double, int, std::string)
    {
        cout << "non-const" << endl;
        return "";
    }
};
 
 
 
int main()
{
    Foo foo;
 
    std::function<std::string(double, int, std::string)> 
        callback = std::bind(&Foo::getValue, &foo, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
 
 
    callback(3.15, 1, "");
 
}
Error:
cannot determine which instance of overloaded function "Foo::getValue" is intended

Как забиндить метод учитывая, что если будет const Foo foo вызывался другой. Не уж то будете советывать транзитный метод?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.12.2015, 12:58
Ответы с готовыми решениями:

Вызов функции-члена через std::function
Суть в следующем Задача сделать обертку вызывающую функцию член класса с параметрами. Для...

В std::function передать метод класса
Есть класс MyClass и в нем функция void Func(int). Как правильно объявить переменную function на...

Error C2664: std::vector<_Ty>::push: невозможно преобразовать параметр 1 из 'double' в 'const std::string &'
#include &lt;iostream&gt; #include &lt;stack&gt; #include &lt;sstream&gt; #include &lt;string&gt; using namespace...

(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&
astxx::manager::connection::connection(std::basic_string&lt;char, std::char_traits&lt;char&gt;,...

9
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.12.2015, 13:54 2
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Не уж то будете советывать транзитный метод?
Можно просто static_cast`ом привести к указателю на нужную функцию.
А можно и что-то поинтереснее придумать:
Кликните здесь для просмотра всего текста
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
62
63
#include <functional>
#include <string>
#include <iostream>
using namespace std;
 
class Foo
{
public:
    std::string getValue(double, int, std::string) const
    {
        cout << "const" << endl;
        return "";
    }
    std::string getValue(double, int, std::string)
    {
        cout << "non-const" << endl;
        return "";
    }
};
 
template <typename C, typename F>
struct rebuild_function;
 
template <typename C, typename R, typename ...Args>
struct rebuild_function<C, R(Args...)>
{
    using type = R (C::*)(Args...);
};
template <typename C, typename R, typename ...Args>
struct rebuild_function<C, R(Args...) const>
{
    using type = R (C::*)(Args...) const;
};
 
template <typename C, typename F>
auto memfun_cast(typename rebuild_function<C, F>::type f) -> decltype(f)
{
    return f;
}
 
int main()
{
    Foo foo;
 
    using get_value_t = std::string(double, int, std::string);
    using get_value_const_t = std::string(double, int, std::string) const;
 
    std::function<get_value_t> callback1
        = std::bind(memfun_cast<Foo, get_value_const_t>(&Foo::getValue)
                  , &foo, std::placeholders::_1
                        , std::placeholders::_2
                        , std::placeholders::_3);
 
    callback1(3.15, 1, "");
 
    std::function<get_value_t> callback2
        = std::bind(memfun_cast<Foo, get_value_t>(&Foo::getValue)
                  , &foo, std::placeholders::_1
                        , std::placeholders::_2
                        , std::placeholders::_3);
 
    callback2(3.15, 1, "");
}
http://rextester.com/WQOXQZ76254
4
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
01.12.2015, 14:59 3
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от DrOffset Посмотреть сообщение
А можно и что-то поинтереснее придумать:
Я себе для подобных случаев такие вот вспомогательные штуки написал:
C++
1
2
3
4
5
6
7
8
9
10
11
template <typename Sig, typename Class>
constexpr Sig Class::* select_overload( Sig( Class::*fn ) ) noexcept
{
  return fn;
}
 
template <typename Sig>
constexpr Sig* select_overload( Sig( *fn ) ) noexcept
{
  return fn;
}
Юзать как-то так:
C++
1
std::bind(select_overload<std::string(double,int,std::string)const>(&Foo::getValue), &foo, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
5
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
01.12.2015, 15:33  [ТС] 4
Кликните здесь для просмотра всего текста
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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <string>
#include <iostream>
#include <functional>
using namespace std;
 
// ---------------------------------------------- CALLBACK -----------------------------------------------------------------
class Foo
{
public:
    int f(float, string) const
    {
        return 77;
    }
    int f(float, string)
    {
        return 32;
    }
};
 
 
 
// ---------------------------------------------- AUTO DEDUCTION PROCESS ----------------------------------------------------
template<class T> struct help;
 
template<class ClassType, class ReturnType, class... Args>
struct help<ReturnType(ClassType::*)(Args...) const>
{
    typedef std::function<ReturnType(Args...)>
        type;
 
    template<class ClassEncapsulatorOfCallback, ClassEncapsulatorOfCallback callbackMethod>         
    static type init(const ClassType& obj)
    {                                                                                               
 
        const auto lambda = [obj](Args... args) mutable {
            return (obj.*callbackMethod)(std::forward<Args>(args)...);
        };
        return lambda;
    }
};
template<class ClassType, class ReturnType, class... Args>
struct help<ReturnType(ClassType::*)(Args...)>
{
    typedef std::function<ReturnType(Args...)>
        type;
 
    template<class ClassEncapsulatorOfCallback, ClassEncapsulatorOfCallback callbackMethod>
    static type init(ClassType& obj)
    {
 
        const auto lambda = [obj](Args... args) mutable {
            return (obj.*callbackMethod)(std::forward<Args>(args)...);
        };
        return lambda;
    }
};
 
template <typename C, typename F>
struct rebuild_function;
 
template <typename C, typename R, typename ...Args>
struct rebuild_function<C, R(Args...)>
{
    using type = R(C::*)(Args...);
};
template <typename C, typename R, typename ...Args>
struct rebuild_function<C, R(Args...) const>
{
    using type = R(C::*)(Args...) const;
};
template <typename C, typename F>
auto memfun_cast(typename rebuild_function<C, F>::type f) -> decltype(f)
{
    return f;
}
 
 
// ---------------------------------------------- EXAMPLE of USING ----------------------------------------------------------
class B
{
    using get_value_t                       = int(float, string);
    using get_value_const_t                 = int(float, string) const;
 
    using const_callback                    = decltype(memfun_cast<Foo, get_value_const_t>(&Foo::f));
    typedef help< const_callback >          helper_const;
    typedef helper_const::type              MyCallbackTypeConst;
 
    using non_const_callback                = decltype(memfun_cast<Foo, get_value_t>(&Foo::f));
    typedef help< non_const_callback >      helper_non_const;
    typedef helper_non_const::type          MyCallbackTypeNonConst;
    
    MyCallbackTypeConst                     m_callback;
    
public:
    
    B()
    {       
                                                        
    }
    void bind(const Foo* const obj)
    {
        m_callback = helper_const::init< const_callback, &Foo::f>(*obj);
 
        cout << m_callback(3.154F, "privet") << endl;
    }
    void bind(Foo* obj)
    {
        m_callback = helper_non_const::init <non_const_callback, &Foo::f>(*obj);
 
        cout << m_callback(3.154F, "privet") << endl;
    }
};
 
// ---------------------------------------------- MAIN ----------------------------------------------------------
int main()
{
 
    Foo* a1 = new Foo();
    const Foo* a2 = new Foo();
    B* b = new B();
 
 
    b->bind(a1);
    b->bind(a2);
    
}


Что-то у меня не получается автоопределить 81 и 82 строку.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.12.2015, 16:31 5
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Что-то у меня не получается автоопределить 81 и 82 строку.
Что значит не получается?
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
01.12.2015, 16:45  [ТС] 6
Цитата Сообщение от DrOffset Посмотреть сообщение
Что значит не получается?
для автоопределения типа (более того модификатора const) надо написать промежуточный класс помощник, который через тот же &Foo::f не поймет какой метод const/не const ему прислали в качестве параметра шаблона. 81 и 82 помогли классу helper это понять - и еще один helper опять же потребует 81 и 82 строку .
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
01.12.2015, 17:29 7
Цитата Сообщение от DrOffset Посмотреть сообщение
std::function<get_value_t>
Почему в обоих случаях (const/non-const) в std::function передается только get_value_t ? А если сделать std::function<get_value_const_t>(...) — то вообще ошибка компиляции
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.12.2015, 18:14 8
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
для автоопределения
Если я правильно тебя понял, то тут слишком умного "автоопределения" быть не может, т.к. только программист в состоянии разрешить неоднозначность между перегруженными функциями. Поэтому тип функции должен быть указан явно (либо выведен явно из другого контекста). Но "само в себе" оно работать не будет.

Цитата Сообщение от gromo Посмотреть сообщение
Почему в обоих случаях (const/non-const) в std::function передается только get_value_t ?
Потому что std::function не учитывает этот const в параметре (у него даже специализации такой нет). Возможность вызова cv- или не cv-функции класса он определяет по cv объекта, который биндится.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
01.12.2015, 18:24  [ТС] 9
Цитата Сообщение от DrOffset Посмотреть сообщение
тут слишком умного "автоопределения" быть не может
Так я вот и рыл в эту сторону скрыть реализацию автоопределения, и предоставить прозрачный лёгкий способ использования. Но блин камен на камне как начал копать ))))
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.12.2015, 18:32 10
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
лёгкий способ использования
Легче, чем написал Voivoid, не получится
0
01.12.2015, 18:32
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.12.2015, 18:32
Помогаю со студенческими работами здесь

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

отсутствует оператор "<<" соответствующий этим операндам (std::ostream << const std::string)
В 20 строке подсвечиваются красным знаки &lt;&lt;. Пишет, что &quot;отсутствует оператор &quot;&lt;&lt;&quot; соответствующий...

ошибка в программе (cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*')
int main() { string fileName, currWord, currMax = &quot;&quot;; cin&gt;&gt;fileName; ...

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


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru