//---------------------------------------------------------------------------
#include <vector>
#include <algorithm>
using namespace std;
...
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(random(200));
}
}
int searchInt;
int searchFirstMatch(int val) //Функция поиска
{
this->searchInt=val;
vector<int>::iterator result;
result=find_if(entities.begin(), entities.end(), isMatch);
if(result!=entities.end())
return *result;
else
return NULL;
}
private:
vector<int> entities; // Вектор хранилище
bool isMatch(int val) // Функция проверки совпадения
{
return(val==searchInt);
}
};
...
intCollection test;
test.searchFirstMatch(5);
Проблема с алгоритмами STL
В качестве хранилища использую вектор, в качестве алгоритмов поиска - стандартные алгоритмы STL. В частности find_if.
Вот собственно пример такого класса. Естественно максимально упрощенный. В оригинальном классе используется не int тип, но здесь он для примера.
Код:
Собственно ошибка происходит при попытке поиска. Что то компилятору не нравится в ссылке на функцию проверки совпадения.
Код:
result=find_if(entities.begin(), entities.end(), [color=red]isMatch[/color]);
Ума не приложу в чем дело...
а чивой говорит-то?
А говорит вот что:
Код:
[C++ Error]_algobase.c(192): E2468 Value of type void is not allowed;
[C++ Error]_algobase.c(192): E2342 Type mismatch in parameter '__pred'(wanted 'void', got 'void');
[C++ Error]_algobase.c(192): E2342 Type mismatch in parameter '__pred'(wanted 'void', got 'void');
Т.е. похоже не нравится проге указатель на функцию проверки совпадения. Ток че ей надо не пойму...
Самое интересное, что такая фигня происходит, когда все функции запихнуты в класс. Когда они россыпью в коде, то все нормально... :(
result=find_if(entities.begin(), entities.end(), intCollection::isMatch);
if
ну да, или this->isMatch... я думаю должно сканать.
Через namespace тоже :( Не пойму в чем проблема собственно. Вроде как формально все правильно.
Код:
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(rand() % 100);
}
}
void searchFirstMatch(int val) //Функция поиска
{
vector<int>::iterator result;
result=find(entities.begin(), entities.end(),val);
if(result != entities.end()){
cout<<"This element is found "<<*result<<endl;
cout<<"The "<<distance(entities.begin(),result)
<<" is the first divisible by "<<*result<<endl;
copy(result,entities.end(),
ostream_iterator<int>(cout," "));
cout<<endl;
}
else
cout<<"The element : "<<val<<" is not found"<<endl;
}
private:
vector<int> entities; // Вектор хранилище
};
int main()
{
srand(time(0));
intCollection test;
test.searchFirstMatch(5);
return 0;
}
#include <ctime>
#include <algorithm>
using namespace std;
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(rand() % 100);
}
}
void searchFirstMatch(int val) //Функция поиска
{
vector<int>::iterator result;
result=find(entities.begin(), entities.end(),val);
if(result != entities.end()){
cout<<"This element is found "<<*result<<endl;
cout<<"The "<<distance(entities.begin(),result)
<<" is the first divisible by "<<*result<<endl;
copy(result,entities.end(),
ostream_iterator<int>(cout," "));
cout<<endl;
}
else
cout<<"The element : "<<val<<" is not found"<<endl;
}
private:
vector<int> entities; // Вектор хранилище
};
int main()
{
srand(time(0));
intCollection test;
test.searchFirstMatch(5);
return 0;
}
Смотри у Страуструпа на странице 588.Он пишет :
Цитата: Б.Страуструп
Алгоритмы find,find_if возвпащают итератор для первого элемента, удовлетворяющего значению или предикату соответственно. Фактически,find можно рассматривать как версию find_if с предикатом равно.Почему бы обе эти функции не назвать find ? Прчина в том,что перегрузка функций не всегда различает вызовы двух шаблоных функций с одинаковым числом аргументов...
А мне нужно выяснить равенство не самого класса, а определенных переменных этого класса(полей), для чего я пишу функцию сравнения этих полей (isMatch).
По этому и нужен find_if. Но указатель на функцию предиката не хочет восприниматься внутри find_if, если алгоритм выполняется внутри класса. Если все функции вне класса расписать, то работает. (!?)
За примерчик спасибо, но не совсем то...
Кажется ситуация начинает немного проясняться... Похоже виной всему некоторые косяки с получением адреса внутриклассовой функции.
Код:
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(random(200));
}
}
int searchInt;
int searchFirstMatch(int val) //Функция поиска
{
this->searchInt=val;
vector<int>::iterator result;
[color=red]bool (*p)(int);//создаем указатель на функцию типа isMatch
//Дальше самое интересное...
p=isMatch; //Казалось бы здесь p должен присваиваться адрес функции isMatch, однако компилятор ругается и не хочет этого делать. p=this->isMatch; дает аналогичный результат.
[/color]
result=find_if(entities.begin(), entities.end(), isMatch);
if(result!=entities.end())
return *result;
else
return NULL;
}
private:
vector<int> entities; // Вектор хранилище
bool isMatch(int val) // Функция проверки совпадения
{
return(val==searchInt);
}
};
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(random(200));
}
}
int searchInt;
int searchFirstMatch(int val) //Функция поиска
{
this->searchInt=val;
vector<int>::iterator result;
[color=red]bool (*p)(int);//создаем указатель на функцию типа isMatch
//Дальше самое интересное...
p=isMatch; //Казалось бы здесь p должен присваиваться адрес функции isMatch, однако компилятор ругается и не хочет этого делать. p=this->isMatch; дает аналогичный результат.
[/color]
result=find_if(entities.begin(), entities.end(), isMatch);
if(result!=entities.end())
return *result;
else
return NULL;
}
private:
vector<int> entities; // Вектор хранилище
bool isMatch(int val) // Функция проверки совпадения
{
return(val==searchInt);
}
};
Код:
template <class InputIterator, class Predicate>
InputIterator find_if(InputIterator first, InputIterator last,
Predicate pred) {
while (first != last && !pred(*first)) ++first;
return first;
InputIterator find_if(InputIterator first, InputIterator last,
Predicate pred) {
while (first != last && !pred(*first)) ++first;
return first;
Разве методом класса можно определить шаблон?
В стандарте прописано что предикат - "This function object may be a pointer to function, or an object of a type with an appropriate function call operator.". То есть, если я правильно понял, это или самостоятельная функция или объект.
Тут ИМХО проблема с указателем на внутреннюю функцию класса.
Функция isMatch имеет вид bool (int). Указатель для нее определяется как
Код:
bool (*p) (int)
Код:
p=isMatch
Так я ж вам про то и говорю. IsMatch имеет тип bool (intCollection:: ) (int) , а не bool (*)(int).
P.S. Получается, никак кроме
Код:
bool(intCollection::*p)(int);
p=&intCollection::isMatch;
p=&intCollection::isMatch;
Код:
#include <vector>
#include <algorithm>
class IntTest;
template <class InputIterator, typename Predicate, class Object>
InputIterator obj_find_if(InputIterator first, InputIterator last,
Predicate pred, Object * obj) {
while (first != last && !(obj->*pred)(*first)) ++first;
return first;}
typedef bool (IntTest::* comparator)(int) ;
class IntTest
{
private:
int search;
std::vector<int> data;
bool isMatch (int t){if (t==search) return true; return false;};
public:
IntTest()
{
for(int i=0; i<10; ++i)
data.push_back(i);
};
int find(int _search)
{
search = _search;
comparator comp = &IntTest::isMatch;
std::vector<int>::iterator result;
result=obj_find_if(data.begin(), data.end(), comp, this);
if (result!=data.end())
return *result;
else
return -1;
};
};
int main()
{
IntTest test;
int rez = test.find(5);
std::cout << rez << std::endl;
rez = test.find(11);
std::cout << rez << std::endl;
return 0;
}
#include <algorithm>
class IntTest;
template <class InputIterator, typename Predicate, class Object>
InputIterator obj_find_if(InputIterator first, InputIterator last,
Predicate pred, Object * obj) {
while (first != last && !(obj->*pred)(*first)) ++first;
return first;}
typedef bool (IntTest::* comparator)(int) ;
class IntTest
{
private:
int search;
std::vector<int> data;
bool isMatch (int t){if (t==search) return true; return false;};
public:
IntTest()
{
for(int i=0; i<10; ++i)
data.push_back(i);
};
int find(int _search)
{
search = _search;
comparator comp = &IntTest::isMatch;
std::vector<int>::iterator result;
result=obj_find_if(data.begin(), data.end(), comp, this);
if (result!=data.end())
return *result;
else
return -1;
};
};
int main()
{
IntTest test;
int rez = test.find(5);
std::cout << rez << std::endl;
rez = test.find(11);
std::cout << rez << std::endl;
return 0;
}
Цитата: Gigahard
Делаю класс коллекции типов с возможностью параметрического поиска.
В качестве хранилища использую вектор, в качестве алгоритмов поиска - стандартные алгоритмы STL. В частности find_if.
Вот собственно пример такого класса. Естественно максимально упрощенный. В оригинальном классе используется не int тип, но здесь он для примера.
Собственно ошибка происходит при попытке поиска. Что то компилятору не нравится в ссылке на функцию проверки совпадения.
Ума не приложу в чем дело...
В качестве хранилища использую вектор, в качестве алгоритмов поиска - стандартные алгоритмы STL. В частности find_if.
Вот собственно пример такого класса. Естественно максимально упрощенный. В оригинальном классе используется не int тип, но здесь он для примера.
Код:
//---------------------------------------------------------------------------
#include <vector>
#include <algorithm>
using namespace std;
...
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(random(200));
}
}
int searchInt;
int searchFirstMatch(int val) //Функция поиска
{
this->searchInt=val;
vector<int>::iterator result;
result=find_if(entities.begin(), entities.end(), isMatch);
if(result!=entities.end())
return *result;
else
return NULL;
}
private:
vector<int> entities; // Вектор хранилище
bool isMatch(int val) // Функция проверки совпадения
{
return(val==searchInt);
}
};
...
intCollection test;
test.searchFirstMatch(5);
#include <vector>
#include <algorithm>
using namespace std;
...
class intCollection
{
public:
intCollection()
{
for(int i=0; i<50; i++)
{
entities.push_back(random(200));
}
}
int searchInt;
int searchFirstMatch(int val) //Функция поиска
{
this->searchInt=val;
vector<int>::iterator result;
result=find_if(entities.begin(), entities.end(), isMatch);
if(result!=entities.end())
return *result;
else
return NULL;
}
private:
vector<int> entities; // Вектор хранилище
bool isMatch(int val) // Функция проверки совпадения
{
return(val==searchInt);
}
};
...
intCollection test;
test.searchFirstMatch(5);
Собственно ошибка происходит при попытке поиска. Что то компилятору не нравится в ссылке на функцию проверки совпадения.
Код:
result=find_if(entities.begin(), entities.end(), [color=red]isMatch[/color]);
Ума не приложу в чем дело...
Ну в чем дело тебе уже рассказали.
Расскажу, что делать. Но сначала поругаю. :)
Какое отношение searchInt имеет к классу intCollection ?
Ответ: никакого!
Тогда какого такое поле существует в этом классе?
Вывод: не захламляйте классы не нужными полями.
Теперь, как решить проблему.
На столько просто, что просто приведу код:
Код:
int searchFirstMatch(int val) //Функция поиска
{
class Comparator {
public:
Comparator(int searchInt) :searchInt(searchInt) {}
bool operator()(int val) {
return (val == searchInt);
}
private:
int searchInt;
};
vector<int>::iterator result;
result = find_if(entities.begin(), entities.end(), Comparator(val));
{
class Comparator {
public:
Comparator(int searchInt) :searchInt(searchInt) {}
bool operator()(int val) {
return (val == searchInt);
}
private:
int searchInt;
};
vector<int>::iterator result;
result = find_if(entities.begin(), entities.end(), Comparator(val));
Еще немного бурчания.
Как ты определяешь, удачно ли закончился поиск?
Если ты будешь искать нулевое значение, то ты не узнаешь нашел ты его или нет.
Я бы возвращал, в зависимости от остального кода программы, либо bool, либо итератор, либо прокси-объект.
Ща Ваш вариант попробую :)
Заработало. Кстати... Класс компаратора объявляется вне функции?
Как ты определяешь, удачно ли закончился поиск?
Если ты будешь искать нулевое значение, то ты не узнаешь нашел ты его или нет.
int в данном случае для примера. Никаких проверок. В будущем классе нулевых объектов не будет. По этому ноль и будет сигналом ошибки.