передача указателя на функцию локального класса в std :: list :: sort

Я пытаюсь отсортировать переменную-член типа std :: list с помощью локальной функции. Поскольку C ++ не разрешает локальные функции и, следовательно, Херб Саттер предлагает локальные классы, я получил следующий код. Но я не уверен, как я могу передать указатель на функцию std::list::sort() функция.

void MyClass::UpdateList()
std::map<ClassA*, int> myCustomOrder; //contains order for ClassA objects
class CompareMyClass
{
public:
CompareMyClass(std::map<ClassA*, int>* order) : m_order(order) { }
bool operator()(ClassA *p1, ClassA *p2) {
return m_order->find(p1) < m_order->find(p2);
return false;
}
private:
std::map<ClassA*, int>* m_order;
};

CompareMyClass compareObj(&myCustomOrder); // set the order
// sort the list
m_list.sort(compareObj); // How do I pass a function pointer at this point

}

Я получаю ошибку компилятора

аргумент шаблона не может ссылаться на локальный тип

Спасибо

2

Решение

Пример кода, показывающий перегрузку оператора, статическую функцию (вызов закомментирован) и лямбда-функцию (вызов закомментирован):

#include <iostream>
#include <list>
#include <string>

class names
{
struct name_node
{
std::string name;
inline bool operator< (const name_node &rnode)
{return (this->name < rnode.name);}
static bool compare_node(const name_node & lnode, const name_node & rnode)
{return (lnode.name < rnode.name);}
};

std::list <name_node> name_list;

public:
void get_data();
void sort_data();
void show_data();
};

void names::get_data()
{
name_node nn;
std::string fruits[5] = { "peach", "cherry", "apple", "plum", "banana" };

for (size_t i = 0; i < sizeof(fruits) / sizeof(fruits[0]); i++){
nn.name = fruits[i];
name_list.push_back(nn);
}
}

void names::sort_data()
{
name_list.sort();
//  name_list.sort(names::name_node::compare_node);
//  name_list.sort([this](const name_node & lnode, const name_node & rnode)
//                  {return (lnode.name < rnode.name);});
}

void names::show_data()
{
std::list<name_node>::iterator it;
for(it = name_list.begin(); it != name_list.end(); ++it)
std::cout << (*it).name << std::endl;
};

int main()
{
names n;
n.get_data();
n.sort_data();
n.show_data();
return 0;
}
0

Другие решения

Как отметил хуанхопанза и как вы можете видеть в этот вопрос в c ++ 11 эта проблема больше не существует, так что, возможно, это будет лучший путь, если это возможно.


Если нет, то я нашел решение, которое может оказаться полезным, если у вас есть небольшое количество типов локальных классов (например, компараторы и, возможно, еще пара).
Я взял пример в ранее упомянутом вопросе SO и изменил его так, чтобы он работал под C ++ 03:


#include <iostream>
#include <vector>
#include <algorithm> // std::remove_if
using namespace std;

template <typename T>
class check {
public:
virtual bool operator()(T x) = 0;
};

template <typename T>
struct cheat {
cheat(check<T> *c)  {_c = c;}
bool operator()(T x) {return _c->operator ()(x);}
check<T> *_c;
};

int main() {

int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::vector<int> v( array, array+10 );

class even : public check<int>
{
public:
virtual bool operator()( int x ) { cout<<"Hi"<<endl; return !( x % 2 ); }
};
even e;

remove_if( v.begin(), v.end(),  cheat<int>(&e)); // no error, prints Hi

return 0;
}

Также в https://ideone.com/HY5bIU (составлено с Wall, педантичный тоже …)

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


редактироватьДругой вариант с небольшим отпечатком

#include <iostream>
#include <vector>
#include <algorithm> // std::remove_if
using namespace std;

template <typename T>
class check {
public:
virtual bool operator()(T x) = 0;

struct aid{
aid(check *p){ _c = p;}
check *_c;
bool operator()(T x){
return _c->operator ()(x);
}
};

aid retMe(){
return aid(this);
}
};

int main() {

int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::vector<int> v( array, array+10 );

class even : public check<int>
{
public:
virtual bool operator()( int x ) { cout<<"Hi"<<endl; return !( x % 2 ); }
};
even e;

remove_if( v.begin(), v.end(), e.retMe()); // no error

return 0;
}

https://ideone.com/6SZ4UH


Здесь aid класс скрыт внутри самого абстрактного класса, но идея та же самая.

Он добавляет некоторый ненужный код, но, с другой стороны, он не такой гротескный, как некоторые хаки.

0

По вопросам рекламы [email protected]