информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяСетевые кракеры и правда о деле ЛевинаСтрашный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Очередное исследование 19 миллиардов... 
 Оптимизация ввода-вывода как инструмент... 
 Зловреды выбирают Lisp и Delphi 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
если вы видите этот текст, отключите в настройках форума использование JavaScript
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
[C++] Function Objects - таки как пользоваться? 08.05.03 16:51  Число просмотров: 1213
Автор: dl <Dmitry Leonov>
<"чистая" ссылка>
> Пытался пробиться через дебри STL, но там тот же for_each
> принимает
> КЛАСС (!) - параметр шаблона которым
> собственно и является. (Хотя при использовании for_each я
> явно ему параметр не передаю т.е. испльзую как обычную
> фунцкию).
> Вот так. Кто что скажет?

Ну так и for_each в STL описан не как функция, получающая параметр-указатель на функцию, а как

template<class _InIt, class _Fn1> inline_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func).
_Fn1 превращается в TraveseFuncPtr только при передаче ему указателя на Add7.
<programming>
[C++] Function Objects - таки как пользоваться? 08.05.03 16:20  
Автор: ilushka Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Здравствуйте!

Вот собственно вопрос:

У Страусдоха доходчиво вроде в в Параграфе 18.4 его Книги описано как пользоваться Function Objects. И пример работает, и если самому это дело использовать тоже работает нормально. Вот простой пример:

void Add7(int& out_Int) 
{
	out_Int += 7;
}

class AddNumber 
{
public:
	int m_iToAdd;

	AddNumber(int in_iToAdd = 0) 
	{
		m_iToAdd = in_iToAdd;
	}	

	void operator()(int& out_Int) 
	{
		out_Int += m_iToAdd;
	}
};

class A 
{
public:
	std::vector < int > m_vData;
};

void main() 
{

	A tmp_a;

	tmp_a.m_vData.push_back(7);
	tmp_a.m_vData.push_back(5);
	tmp_a.m_vData.push_back(6);

	std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7);

	std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13));

}


---

Но вот как только пытаюсь использовать их сам вот например таким образом:

typedef void (*TraveseFuncPtr) (int&);

void Add7(int& out_Int) 
{
	out_Int += 7;
}

class AddNumber 
{
public:
	int m_iToAdd;

	AddNumber(int in_iToAdd = 0) 
	{
		m_iToAdd = in_iToAdd;
	}	

	void operator()(int& out_Int) 
	{
		out_Int += m_iToAdd;
	}
};

class A 
{
public:
	std::vector < int > m_vData;
	void TraverseVector(TraveseFuncPtr in_func) 
	{
		for (int i = 0; i < m_vData.size(); i++) 
		{
			(*in_func)(m_vData[i]);
		}
	}
};

void main() 
{
	A tmp_a;

	tmp_a.m_vData.push_back(7);
	tmp_a.m_vData.push_back(5);
	tmp_a.m_vData.push_back(6);

	tmp_a.TraverseVector(Add7); // All ok.

	tmp_a.TraverseVector(AddNumber(13)); //C2664
}

---

Сразу получаю облом.

error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Пытался пробиться через дебри STL, но там тот же for_each принимает
КЛАСС (!) - параметр шаблона которым собственно и является. (Хотя при использовании for_each я явно ему параметр не передаю т.е. испльзую как обычную фунцкию).

Вот так. Кто что скажет?
[C++] Function Objects - таки как пользоваться? 08.05.03 16:51  
Автор: dl <Dmitry Leonov>
<"чистая" ссылка>
> Пытался пробиться через дебри STL, но там тот же for_each
> принимает
> КЛАСС (!) - параметр шаблона которым
> собственно и является. (Хотя при использовании for_each я
> явно ему параметр не передаю т.е. испльзую как обычную
> фунцкию).
> Вот так. Кто что скажет?

Ну так и for_each в STL описан не как функция, получающая параметр-указатель на функцию, а как

template<class _InIt, class _Fn1> inline_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func).
_Fn1 превращается в TraveseFuncPtr только при передаче ему указателя на Add7.
[C++] Function Objects - таки как пользоваться? 08.05.03 16:48  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Сразу получаю облом.
>
> error C2664: 'TraverseVector' : cannot convert parameter 1
> from 'class AddNumber' to 'void (__cdecl *)(int &)'
> No user-defined-conversion operator available that
> can perform this conversion, or the operator cannot be
> called
Ну да объект-функция все-таки остается объектом. И такое преобразование невозможно (вернее ты его не опредилил). Есть несколько вариантов:
1) Самому перегрузить TraverseVector, чтоб он принимал еще и объекты класса AddNumber
2) Добавить в AddNumber преобразование operator TraveseFuncPtr(), но тогда ты потеряешь параметр
3) ИМХО самый правильный вариант. Поступить как сделано в STL. "Тот же for_each" принимает класс, потому как он может принять ЛЮБОЙ объект, к которому применим operator(). К объекту типа void (*) (int&) он применим (как и к любому указателю на функцию), а в классе AddNumber он перегружен и тоже применим. Поэтому шаблон инстанцируется дважды (короче два разных кода одной функции получается): один раз для указателя и один раз для AddNumber-а. Если кода не сильно много, то можно не заморачиваться с эффективностью и частичной спецификацией шаблонов и сделать следующее:

class A {
public:
std::vector < int > m_vData;
template <class T>
void TraverseVector(T in_func) {
for (int i = 0; i < m_vData.size(); i++)
in_func(m_vData[i]);
}
};

> Пытался пробиться через дебри STL, но там тот же for_each
> принимает
> КЛАСС (!) - параметр шаблона которым
> собственно и является. (Хотя при использовании for_each я
> явно ему параметр не передаю т.е. испльзую как обычную
> фунцкию).
Можно прочитать у того же Страуструпа :-) про выведение типа шаблона. Короче, явно указывать тип параметра шаблона не надо если компилятор сам может его вывести. В частности он может сделать это по агрументам шаблонной функции.

>
> Вот так. Кто что скажет?
[C++] Function Objects - таки как пользоваться? 10.05.03 10:10  
Автор: ilushka Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Спасибо большое все понял ;)
[C++] Функтор (functional object) и указатель на функцию - не одно и то же, если не использовать шаблон 08.05.03 16:48  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
Отредактировано 08.05.03 16:52  Количество правок: 2
<"чистая" ссылка>
Элементарно, Ватсон. Вы сначала объявляете TraverseFuncPtr как указатель на функцию:
typedef void (*TraveseFuncPtr) (int&);

---
и A::TraverseVector как принимающий этот указатель параметром:
> class A 
> {
> public:
> 	std::vector < int > m_vData;
> 	void TraverseVector(TraveseFuncPtr in_func) 
> 	{
> 		for (int i = 0; i < m_vData.size(); i++) 
> 		{
> 			(*in_func)(m_vData[i]);
> 		}
> 	}
> };

---
но после этого вы пытаетесь подсунуть вместо указателя на функцию что-то совершенно другое - объект, не имеющий неявного приведения к TraverseFuncPtr:
tmp_a.TraverseVector(AddNumber(13)); //C2664

---
Естественно, компилятор обижается.

> Пытался пробиться через дебри STL, но там тот же for_each
> принимает
> КЛАСС (!) - параметр шаблона которым
> собственно и является. (Хотя при использовании for_each я
> явно ему параметр не передаю т.е. испльзую как обычную
> фунцкию).
Не дайте себя запутать. Параметром шаблона может быть ЛЮБОЙ ТИП, хоть int. Правда, внутри for_each стоит вызов этого самого шаблонного "объекта" со скобками, в результате возможные варианты ограничиваются указателем на функцию либо объектом имеющим operator() (больше ничего такой синтаксис не переварит).

Итого. Если вы хотите передавать и указатели на функции, и функторы, у вас два варианта:
1) TraverseVector принимает на входе объект unary_function или binary_function (внимание - не по значению! иначе произойдет срезка типа). Функторы наследуются от unary_functin/binary_function. Указатели на функции при передаче обертываются в unary_function/binary_function (см. ptr_fun у Страуструпа)
2) TraverseVector объявляется шаблоном и на принимает параметр с шаблонным типом. Тогда он ничем по способу работы с параметрами не будет отличаться от for_each.

Есть еще и третий вариант:
3) Не использовать TraverseVector, а выкрутиться через for_each и чуть более сложный функтор, который будет, например, другом класса A. Идеологически это более правильно, особенно если есть возможность обойтись без дружественных отношений классов.
[C++] Функтор (functional object) и указатель на функцию - не одно и то же, если не использовать шаблон 10.05.03 10:14  
Автор: ilushka Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Тоже все понял, спасибо ;)
Пожалуйста :) Тогда нажми "закрыть" на корневом посте 11.05.03 12:21  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach