информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Атака на InternetSpanning Tree Protocol: недокументированное применениеВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[C++] Function Objects - таки как пользоваться? 08.05.03 16:51  Число просмотров: 1131
Автор: 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-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach