Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> приведение указателя на метод в иерархии классов 
V
    Опции темы
georain
Дата 14.10.2010, 06:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Код

struct Base
{
    void foo();
};

class Derived: public Base {};

static const void(Derived::*Foo)(void) =  &Derived::foo;


В последней строке ошибка преобразования. Вопрос почему, или как мне зарегистрировать foo как callback:

Код

void call(Derived * object, void(Derived::*memFun)(void) )
{
    ( object->*memFun )();
}
....
call(this, Foo);


Ведь метод foo является методом как базового так и производного класса.
PM MAIL   Вверх
mes
Дата 14.10.2010, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  14.10.2010,  05:56 Найти цитируемый пост)
В последней строке ошибка преобразования.  Вопрос почему,  

а текст ошибки зачем скрываете ?

Цитата(georain @  14.10.2010,  05:56 Найти цитируемый пост)
static const void(Derived::*Foo)(void) =  &Derived::foo;

это не константный указатель, а указатель на константу.. и соответсвенно будет вызывать конфликт в call(..);

Код

static void(Derived::* const Foo )(void) =  &Derived::foo;


Это сообщение отредактировал(а) mes - 14.10.2010, 08:18


--------------------
PM MAIL WWW   Вверх
georain
Дата 14.10.2010, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Цитата(mes @  14.10.2010,  08:14 Найти цитируемый пост)
это не константный указатель, а указатель на константу..

Вы совершенно правы, спасибо большое.

Но моя проблема лишь отодвинулась немного дальше.
Требуется вызвать шаблонный метод наподобие этого:
Код

template <void(Derived::*MemFun)(void)>
void template_call(Derived * object)
{
    ( object->*MemFun )();
}


Метод объявленный непосредственно в классе Derived вызывается без проблем, а метод из базового класса вызываться не хочет.
Код

struct Base
{
    void foo();
};

struct Derived: public Base
{
    void moo();
};

void g(Derived * d)
{
    template_call<&Derived::moo>(d); // ok
    template_call<&Derived::foo>(d); // нет соответствующей функции для вызова call(Derived*&)
}


Для этого я и пытался сделать приведение, но и этого сделать не удалось:
Код

// объявление статической константы
static void(Derived::*const Foo)(void) =  &Derived::foo;

// другой вариант объявления статической константы
typedef decltype(&Derived::foo) FooPtrType;
static const FooPtrType Goo =  &Derived::foo;

void g(Derived * d)
{
    template_call<Foo>(d); // Foo cannot appear in a constant-expression
    template_call<Goo>(d); // Goo cannot appear in a constant-expression
}

PM MAIL   Вверх
mes
Дата 14.10.2010, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  14.10.2010,  19:52 Найти цитируемый пост)
// нет соответствующей функции для вызова call(Derived*&)

Код

template <class T>
void template_call(void(T::*MemFun)(), Derived * object)
{
    ( object->*MemFun )();
}

void g(Derived * d)
{
    template_call(&Derived::moo, d); 
    template_call(&Derived::foo, d); 
}


Добавлено через 2 минуты и 23 секунды
это в качестве изучения или решаете какую то практическую задачу ?
если второе то велосипеды уже изобретены smile 
например boost::function, он же (на совр компиляторах) std::(tr1::)function;



--------------------
PM MAIL WWW   Вверх
georain
Дата 15.10.2010, 00:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Спасибо за вариант, но требуется статическая передача указателя для того чтобы компилятор мог сделать inline.

В общем случае
Код

template <typename ClassType, typename Result, typename... Arguments>
template <Result(ClassType::*MemFun)(Arguments...)>
void template_call(ClassType * object, Arguments &&... args)
{
    ( object->*MemFun )(std::forward<Arguments...>(args...));
}


И блин, у меня уже целый год пол проекта на этом работает, а тут бац, метод из базового класса передать не могу. В принципе решается то просто, добавлением в нужный класс метода с вызовом метода из базового, но это же ерунда.

Занимаюсь распределенными системами и асинхронным выполнением.

Это сообщение отредактировал(а) georain - 15.10.2010, 01:20
PM MAIL   Вверх
mes
Дата 15.10.2010, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  14.10.2010,  23:58 Найти цитируемый пост)
но требуется статическая передача указателя для того чтобы компилятор мог сделать inline.

 smile ммм... и откуда такие сведенья ?!

Добавлено через 2 минуты и 6 секунд
заинлайненая фунция, эта такая "функция" которую не возможно вызвать по адресу, через указатель smile
ничего противоречивого не замечаете ? smile



--------------------
PM MAIL WWW   Вверх
georain
Дата 15.10.2010, 08:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Цитата(mes @  15.10.2010,  08:12 Найти цитируемый пост)
ммм... и откуда такие сведенья ?!

Оптимизирующие компиляторы.

Заинлайненая функция это и не функция, а набор операторов в другой функции.

Ладно, не важно для чего это нужно, почему не работает, как задачку решить, я пока не придумал.
PM MAIL   Вверх
boostcoder
Дата 15.10.2010, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



[offtop]
Цитата(georain @  15.10.2010,  00:58 Найти цитируемый пост)
Arguments...

variadic templates? smile 
микрософтстудия?
у кого есть такой компилятор, скажите пожалуйста, что говорит на такие выражения:
Код

template<typename Args...>
struct tuple_type {
   typedef typename boost::tuple<Args...> type;
};

template<typename Args...>
struct tuple_type {
   typedef typename boost::fusion::tuple<Args...> type;
};

в gcc еще не реализовано :(

спасибо.

[/offtop]

Добавлено @ 08:29
Цитата(georain @  15.10.2010,  08:25 Найти цитируемый пост)
это и не функция

а кто сказал что это функция? сказали что это функция, в кавычках smile 

Это сообщение отредактировал(а) boostcoder - 15.10.2010, 08:30
PM WWW   Вверх
mes
Дата 15.10.2010, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  15.10.2010,  07:25 Найти цитируемый пост)
Заинлайненая функция это и не функция, а набор операторов в другой функции.

поэтому я и взял слово функция в кавычки smile


Цитата(georain @  15.10.2010,  07:25 Найти цитируемый пост)
 не важно для чего это нужно, почему не работает, как задачку решить, я пока не придумал. 

не понимая цели, трудно предложить варианты. которые Вас устроят smile
Код

template <class T, void(T::*MemFun)()>
void template_call(Derived * object)
{
    ( object->*MemFun )();
}

void g(Derived * d)
{
    template_call<Derived, &Derived::moo>(d); 
    template_call<Base, &Derived::foo>(d); 
}





--------------------
PM MAIL WWW   Вверх
georain
Дата 15.10.2010, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Цитата(boostcoder @  15.10.2010,  08:28 Найти цитируемый пост)
в gcc еще не реализовано

Вариативные шаблоны реализованы, gcc c++0x.
Gcc 4.4 на приведенный код пишет (кстати три точки надо в другом месте ставить):
Код

template <typename... Args>
struct tuple_type {
   typedef typename boost::tuple<Args...> type; // cannot expand ‘Args ...’ into a fixed-length argument list
}

template<typename... Args>
struct tuple_type {
   typedef typename boost::fusion::tuple<Args...> type; // ‘tuple’ in namespace ‘boost::fusion’ does not name a type
}



mes, ещё раз спасибо за работающий фрагмент. Сейчас у меня цель понять и разобраться, почему не работают некоторые выражения:
Код

template_call<&Derived::foo>(d); // нет соответствующей функции для вызова call(Derived*&)

и
Код

template_call<Foo>(d); // Foo cannot appear in a constant-expression


Например здесь происходит преобразование указателя:
Код

template_call<Base, &Derived::foo>(d);

и так как это выражение корректно, то это наводит меня на мысль, что тип метода foo - void(Base::*)(void), и никак не  void(Derived::*)(void), хотя Derived все-же содержит в себе этот метод. В этом видимо суть проблемы. То что выражение &Derived::foo возвращает указатель с типом  void(Base::*)(void)...
PM MAIL   Вверх
boostcoder
Дата 15.10.2010, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(georain @  15.10.2010,  09:04 Найти цитируемый пост)
Gcc 4.4

что пишет gcc-4.4.* мне не интересно.
PM WWW   Вверх
georain
Дата 15.10.2010, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Так ну вроде бы начинает доходить, хотя я это изначально как-то интуитивно воспринимал, поэтому и хотел сделать преобразование
Код

static void(Derived::*const Foo)(void) =  &Derived::foo;

Но почему теперь эту константу в параметр шаблона то не получается загнать.

Добавлено через 21 секунду
Цитата(boostcoder @  15.10.2010,  09:07 Найти цитируемый пост)
что пишет gcc-4.4.* мне не интересно. 

А что интересно?

Добавлено через 1 минуту и 31 секунду
Если микрософтстудия, то они там ещё не скоро появятся.
PM MAIL   Вверх
mes
Дата 15.10.2010, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  15.10.2010,  08:04 Найти цитируемый пост)
То что выражение &Derived::foo возвращает указатель с типом  void(Base::*)(void)... 

 smile 
поэтому :
Цитата(georain @  15.10.2010,  08:04 Найти цитируемый пост)
// нет соответствующей функции для вызова call(Derived*&)


Цитата(georain @  15.10.2010,  08:04 Найти цитируемый пост)
Foo cannot appear in a constant-expression

ну а тут результат выражения не известен в компильтайм.




--------------------
PM MAIL WWW   Вверх
djamshud
Дата 15.10.2010, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 8
Всего: 39



Не так давно тут был небольшой срач, так вот, по результатм: функция, передаваемая по указателю, вполне может инлайниться в код, если во время компиляции не обнаруживается, что адрес указателя может измениться в рантайме - по сути это условие использования тех же шаблонов; выяснилось также, что такое поведение зависит от компилятора и его версии.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
mes
Дата 15.10.2010, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(georain @  15.10.2010,  08:09 Найти цитируемый пост)
Но почему теперь эту константу в параметр шаблона то не получается загнать.

потому что это const, а не constexpr (константное выражение)

Добавлено @ 09:14
Цитата(djamshud @  15.10.2010,  08:11 Найти цитируемый пост)
Не так давно тут был небольшой срач, так вот, по результатм: функция, передаваемая по указателю, вполне может инлайниться в код, если во время компиляции не обнаруживается, что адрес указателя может измениться в рантайме - по сути это условие использования тех же шаблонов; выяснилось также, что такое поведение зависит от компилятора и его версии

да.. но передача адреса фанкции в шаблон не увеличивает шансы на ее заинлайненость - именно об этом и шла речь выше.. 

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


Это сообщение отредактировал(а) mes - 15.10.2010, 09:18


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0938 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.