2015-02-25 1 views
0

Я хочу создать пользовательский метод сравнения для std :: set, который использует кешированные значения охватывающего класса (в котором задан набор).В C++, как позволить (вложенному) функтору сравнения ссылаться на данные охватывающего класса?

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

Но мой вопрос заключается в том, как вы импортируете такой указатель (pModel в моем скелете кода) в функции сравнения?

Мой код скелет:

using namespace std; 
class Face; 

class Model 
{ 
public: 
    // ... 
    map<Face, double> areaCached; 

    double area(Face f) 
    { 
     if (areaCached.find(f) == areaCached.end()) 
     { 
      double calculatedValue; // perform very expensive calculation 
      areaCached[f] = calculatedValue; 
     } 
     return areaCached[f]; 
    } 

    struct CompareByArea 
    { 
     // how can I import the pModel pointer here? 

     bool operator() (const Face f1, const Face f2) const 
     { 
      return pModel->area(f1) < pModel->area(f2); 
     } 
    }; 

    set<Face, CompareByArea> sortedFaces; 

}; 
+0

Надеюсь, вы понимаете, что изменение модели аннулирует набор 'sortedFaces', и вам нужно будет очистить его и полностью воссоздать? – Slava

+0

Да, абсолютно .. любая смена модели может добавить лица или изменить площадь лиц. Поэтому изменения модели должны приводить к аннулированию всех видов кэшированной информации (например, sortedFaces) .. но спасибо за указание в любом случае! –

ответ

3

Различные ассоциативные контейнеры принимают объект сравнения в качестве параметра конструктора. То есть, вы должны добавить указатель на свою функцию сравнения и добавить конструктор, устанавливающий этот указатель. Тогда вы строите вы установили соответственно:

class Model { 
    struct CompareByArea { 
     Model* model; 
     CompareByArea(Model* model): model(model) {} 
     bool operator()(Face const& f1, Face const& f2) const { 
      return model->area(f1) < model->area(f2); 
     } 
    }; 
    std::set<Face, CompareByArea> sortedFaces; 
    // ... 
public: 
    Model(): sortedFaces(CompareByArea(this)) {} 
    // ... 
}; 

Использование this может выдавать предупреждения об использовании this, прежде чем он полностью построен, но до тех пор, как this не использовать в конструкторе CompareByArea для доступа к Model там ISN» проблема.

2

Я приведу вам пример со ссылками, только потому, что я предпочитаю их указатели.

struct CompareByArea 
{ 
    CompareByArea(Model& aModel):model(aModel) 

    bool operator() (const Face& f1, const Face& f2) const 
    { 
     return model.area(f1) < model.area(f2); 
    } 

    Model& model; 
}; 

И вы должны рекомендовать ссылки по указателям на C++. Это легче читать и понимать.

+0

Да, но как мне определить свой набор сейчас? (Конструктор std :: set не ожидает конструктора по умолчанию для функтора?) –

+0

Да, вы правы. Ответ Дитмара справляется с этим. –

+0

Вы забыли и в модели модели; член – Slava

Смежные вопросы