Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Взятие адреса перегруженного метода класса / 11 сообщений из 11, страница 1 из 1
01.10.2015, 11:16
    #39065908
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
В шаблонную функцию нужно передать адрес перегруженного метода некоторого класса:

Код: plaintext
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.
struct Foo
{
    void MySignal()   {}
    void MySignal(int)   {}
};

template <typename Signal>
void Connect( Signal signal )
{
}

void Test()
{
    // Не компилируется:
    // Connect( &Foo::Signal );

    // Компилируется, но жутко неудобно:
    Connect( static_cast<void (Foo::*)(int)>(&Foo::MySignal) );

    // Пробуем макросы с переменным числом аргументов. Работает.
    #define signal(a_class, a_method, ...) \
        static_cast<void (a_class::*)(__VA_ARGS__)>(&a_class::a_method)

    Connect( signal(Foo, MySignal, int) );
}



А теперь нужно макрос signal переделать на шаблонную функцию с переменным числом аргументов. Как-то так:

Код: plaintext
1.
2.
3.
4.
5.
6.
template <typename t_class, typename... t_arguments>
    decltype(void (t_class::*)(t_arguments))
        Signal( void (t_class::*ptr)(t_arguments...) )
{
    return static_cast<void (a_class::*)(t_arguments)>(ptr);
}



Это заведомо неверно, но у меня даже идей не возникает как это сделать правильнее. А у вас идеи есть?
...
Рейтинг: 0 / 0
01.10.2015, 13:20
    #39066094
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
petrav,

Так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
template <typename t_class, typename... t_arguments>
    auto Signal( void (t_class::*ptr)(t_arguments...) )
{
    return static_cast<void (t_class::*)(t_arguments...)>(ptr);
}
void Test()
{
Connect( Signal<Foo, int>(&Foo::MySignal) ); 
}



Можете ещё глянуть в сторону std::result_of
...
Рейтинг: 0 / 0
01.10.2015, 13:39
    #39066123
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
NekZpetrav,

Так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
template <typename t_class, typename... t_arguments>
    auto Signal( void (t_class::*ptr)(t_arguments...) )
{
    return static_cast<void (t_class::*)(t_arguments...)>(ptr);
}
void Test()
{
Connect( Signal<Foo, int>(&Foo::MySignal) ); 
}



Можете ещё глянуть в сторону std::result_of
Увы. Выдаёт "error C3551: expected a trailing return type". Студия 2013.

Если уж типа auto возвращаем, то можно так, наверное:
Код: plaintext
1.
2.
3.
4.
5.
6.
template <typename t_class, typename... t_arguments>
    auto Signal( void (t_class::*ptr)(t_arguments...) ) ->
        decltype( void (t_class::*ptr)(t_arguments...) )
{
    return static_cast<void (t_class::*)(t_arguments...)>(ptr);
}



Но результат как и у меня раньше плачевный: error C2893: Failed to specialize function template 'unknown-type test::Signal(void (__thiscall t_class::* )(t_arguments...))'.

Где он там неизвестный тип нашёл непонятно.
...
Рейтинг: 0 / 0
01.10.2015, 13:59
    #39066151
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
petrav,

Увы, на 14 стандарте это работает, на 11 нет, проверял на g++ 5.2.1

Можно попробовать так, decltype там не нужен, он нужен лишь для выведения типа из какого-либо выражения, как раз если trailing type вывести можно одним выражением.
Код: plaintext
1.
2.
3.
4.
5.
template <typename t_class, typename... t_arguments>
    auto Signal( void (t_class::*ptr)(t_arguments...) ) -> void (t_class::*)(t_arguments...)
{
    return static_cast<void (t_class::*)(t_arguments...)>(ptr);
}
...
Рейтинг: 0 / 0
01.10.2015, 14:04
    #39066155
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
А вообще, нахрена такое извращение, когда есть (std|boost)::function???
...
Рейтинг: 0 / 0
01.10.2015, 14:25
    #39066176
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
NekZА вообще, нахрена такое извращение, когда есть (std|boost)::function???
А это система слотов и сигналов из Qt5, которая теперь аля boost::signals. Я её не упоминал напрямую, что бы расширить аудиторию обсуждения. :)

Нам нужно только написать функцию Signal.

Кстати, Ваш последний код откомпилировался. Спасибо. :)

Я так понимаю, тут нельзя избавиться от повтора названия класса Foo?
Код: plaintext
1.
Connect( Signal<Foo, int>(&Foo::MySignal) );
...
Рейтинг: 0 / 0
01.10.2015, 14:42
    #39066193
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
petravNekZА вообще, нахрена такое извращение, когда есть (std|boost)::function???
А это система слотов и сигналов из Qt5, которая теперь аля boost::signals. Я её не упоминал напрямую, что бы расширить аудиторию обсуждения. :)


Совсем ни разу. Это хитрая и гибкая реализация функторов с возможностью частичного применения через std::bind.

petravЯ так понимаю, тут нельзя избавиться от повтора названия класса Foo?
Код: plaintext
1.
Connect( Signal<Foo, int>(&Foo::MySignal) );



Ну, если бы можно это было бы как-то завернуть в автовыведение типа, то наверное.
...
Рейтинг: 0 / 0
01.10.2015, 14:55
    #39066203
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
NekZpetravпропущено...

А это система слотов и сигналов из Qt5, которая теперь аля boost::signals. Я её не упоминал напрямую, что бы расширить аудиторию обсуждения. :)


Совсем ни разу. Это хитрая и гибкая реализация функторов с возможностью частичного применения через std::bind.

Да нет же. Это я, формулируя исходную задачу, на самом деле описывал систему слоты-сигналы из Qt5. И возникшую с ними проблему.

Думаю, std::function туда ну ни как не прикрутить. :)

NekZpetravЯ так понимаю, тут нельзя избавиться от повтора названия класса Foo?
Код: plaintext
1.
Connect( Signal<Foo, int>(&Foo::MySignal) );



Ну, если бы можно это было бы как-то завернуть в автовыведение типа, то наверное.

Как это сделать у меня идей нет. :(
...
Рейтинг: 0 / 0
01.10.2015, 21:15
    #39066492
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
boost::signals2 ?
...
Рейтинг: 0 / 0
01.10.2015, 22:31
    #39066527
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
alexy_blackboost::signals2 ?
Да. Раньше в Qt это решали с помощью собственного макропроцессора + кодагенератора. Теперь вот добавили поддержку чистого С++. Даже макрос «slot» уже не обязателен.
...
Рейтинг: 0 / 0
02.10.2015, 12:33
    #39066990
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взятие адреса перегруженного метода класса
petravВ шаблонную функцию нужно передать адрес перегруженного метода некоторого класса:
...
Это заведомо неверно, но у меня даже идей не возникает как это сделать правильнее. А у вас идеи есть?

Код даже не читал.

Если у тебя код шаблонный, то ты просто можешь без передачи адреса функции её вызывать по имени
везде, где нужно. Компилятор сам её найдёт, а если не найдёт -- ругнётся.

Это конечно, если делать это нужно исключительно в compile-time.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Взятие адреса перегруженного метода класса / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]