2012-04-20 4 views
2

У меня есть класс с функциейPass пользовательского компаратор через функцию

MyClass::doStuff(std::vector<MyCustomData*> toSort) { ... 

, в которых я называю

std::sort(toSort.begin(), toSort.end(), MyClass::SortByZ()); 

MyClass :: SortByZ() обычай компаратор. Теперь это работает, но я хотел бы достичь:

У меня есть несколько классов, каждый из которых должен иметь свой собственный функтор компаратора для сортировки «MyCustomData». Так, например, Class1 ... должны иметь

class Class1 { 
    struct SortData { 
     bool operator()(MyCustomData *lhs, MyCustomData *rhs) { 
     return lhs->something1 > rhs->something1; 
     } 
    }; 
    //...many more functions/vars 
} 

в то время как Class2 имеет другой компаратор функтор для того же типа данных, например,

class Class2 { 
    struct SortData { 
     bool operator()(MyCustomData *lhs, MyCustomData *rhs) { 
     return lhs->something2 > rhs->something2; 
     } 
    }; 
    //...many more functions/vars 
} 

Теперь я хотел бы иметь возможность вызвать функцию MyClass :: DoStuff (.. .) либо с

doStuff(myData, Class1::SortData) 

или

doStuff(myData, Class2::SortData) 

и функция MyClass :: doStuff (...) должна использовать соответствующий порядок сортировки.

Я не нашел способ сделать это, есть ли он? Я хотел бы простое решение (не нужно поддерживать шаблоны или что-то еще). Я был бы готов использовать boost, если бы мне это было нужно, но было бы предпочтительным решение без повышения.

Надеюсь, я смог описать, чего я хочу достичь? Спасибо за любую помощь!

+1

Если ваш 'vector' хранит объекты MyCustomData', а не указатели, функторы' SortData' должны иметь другую подпись: 'bool operator() (MyCustomData const & lhs, MyCustomData const & rhs)'. –

+0

Извините, я не знал об этом. Вектор хранит указатели, поэтому вектор , поэтому работает сигнатура функтора. – Ela782

ответ

5

Вам придется сделать doStuff шаблон:

template <typename Comparator> 
void doStuff(std::vector<MyCustomData*> toSort, Comparator compare) { 
    // ... 
    std::sort(toSort.begin(), toSort.end(), compare); 
    // ... 
} 

Кроме того, она может понадобиться, чтобы сделать первый аргумент по ссылке. Как бы то ни было, он сортирует копию аргумента, отбрасывает эту копию и оставляет вектор вызывающего нетронутым; хотя, возможно, это то, чего вы хотите.

+0

Спасибо за ваш ответ, а также Люку! Я только что нашел еще две идеи, которые могли бы работать и помогать мне. Можно ли вызвать функцию сравнения/функтор с аргументом (строкой)? Затем я бы назвал doStuff (myData, «SortByThis»), и компаратор мог бы делать 'bool operator (... string sortByThis? ...) (MyCustomData const & lhs, MyCustomData const & rhs) {' '. ..return lhs.something.find [sortByThis] -> second> rhs.something.find [sortByThis] -> second; ' Потому что я сортирую по некоторым данным в этой std :: map что-то. – Ela782

+0

Вторая идея заключалась бы в том, чтобы предоставить структуре переменную 'string SortByThis' и использовать ее в operator() или создать структуру класса, создать ее экземпляр, установить SortByThis в мою нужную строку и использовать ее? Думаю, я собираюсь попробовать все три. Есть ли что-то лучше, чем другое с точки зрения программного обеспечения? – Ela782

+0

@ Ela782: Второй способ - как вы это сделаете. Вы не можете изменить оператор функции-оператора компаратора; это должно быть что-то вроде 'bool operator() (T a, T b);' без дополнительных аргументов. Но вы можете поместить данные в компаратор и использовать их в операторе. –

2

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

template <typename Comparator> 
void doStuff(std::vector<MyCustomData> toSort, Comparator comparator) 
{ 
    ... 
    std::sort(toSort.begin(), toSort.end(), comparator); 
    ... 
} 
... 
doStuff(myData, Class1::SortData()); 
doStuff(myData, Class2::SortData()); 

Это как стандартные алгоритмы обеспечивают типичность.

+0

Жаль, что я могу принять только один ответ, так как ваш тот же и одинаково полезный. И вы, вероятно, были только медленнее, потому что вы впервые ввели комментарий о моей неправильной сигнатуре функтора. Поэтому я не знаю, кого я должен выбрать, я здесь очень новый. Я очень благодарю вас за вашу помощь! – Ela782

+0

@ Ela782: Не волнуйся, я не пропущу 15 очков репутации :). Обычно, когда вопрос имеет несколько одинаковых ответов, принято принимать тот, который пришел первым. В этом случае ответ Майка еще немного лучше, так как он обращает внимание на то, что 'toSort' передается по значению. Я решил удалить мой ответ, но я оставлю его, поскольку он предоставляет образец использования шаблона функции. –

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