2016-10-24 7 views
1

Я ищу «динамический компаратор», который дает результат сравнения в зависимости от аргумента во время выполнения.Является «динамическим компаратором», доступным в C++

Здесь приведен компаратор, который сравнивает два целых числа в соответствии с их расстояниями до входного аргумента x.

struct leq 
{ 
    bool operator()(const int a, const int b, const int x) { 
     return abs(a-x) <= abs(b-x); 
    } 
}; 

я надеюсь использовать его для осуществления следующей вставки в набор, содержащий целое число 2, то есть,

mySet = {2} 

mySet.insert(3, leq(5)) results: mySet = {3, 2} // argument x of leq is 5 and abs(3-5) < abs(2-5) 

mySet.insert(3, leq(1)) results: mySet = {2, 3} // argument x of leq is 1 and abs(3-1) > abs(2-1) 

Note: the argument x may change for each element to be inserted into mySet. 

Есть ли способ использовать только стандартный контейнер набор и функцию его членов для достижения этой цели?

Заранее благодарен!

+2

Какова ваша фактическая проблема, когда вы пишете это? –

+1

Является ли 'x' фиксированным значением для каждого экземпляра' std :: set'? Или вы хотите время от времени изменять значение 'x'? –

+0

Слово, которое вы ищете, является «stateful». – Mehrdad

ответ

4

Вы можете дать ваш компаратор конструктор, чтобы передать его значения во время выполнения:

struct leq 
{ 
    const int x; 
    leq(int x): x(x) {} // constructor 

    bool operator()(const int a, const int b) const { 
     return abs(a-x) < abs(b-x); 
    } 
}; 

// ... 

// construct a set with a comparator set to x = 5 
std::set<int, leq> my_set(leq(5)); 
+0

. My_set.insert() будет использовать 5 для всех элементов, которые будут вставлены в нее, чего я не хочу (см. Мою пересмотренную заметку).Мне что-то не хватает? – leo

+1

@leo Невозможно заказать различные элементы в соответствии с различными критериями. Я также не могу понять, почему это желательно для 'std :: set'. Вам понадобится контейнер, который позволяет произвольный порядок элементов, таких как 'std :: vector'. – Galik

0

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

Наиболее динамичный набор:

template<class T> 
using dynamic_set = std::set<T, std::function<bool(T const&,T const&)>>; 

Тогда:

auto leq(int x){ 
    return [x](int a, int b){ 
    return abs(a-x) < abs(b-x); 
    }; 
} 

дает нам leq.

dynamic_set<int> mySet({2}, leq(5)); 
mySet.insert(3); 

против

dynamic_set<int> mySet({2}, leq(1)); 
mySet.insert(3); 

делает то, что вы хотите, я считаю.

Заменить auto на std::function<bool(int const&, int const&)> в C++ 11 в leq.

+0

Я хочу иметь возможность использовать разные x для каждого элемента, который будет вставлен в тот же набор. Ваше решение кажется только позволяющим использовать разные x для разных наборов. – leo

+0

@ мой первый абзац гласит: «Наборы предполагают, что они всегда сортируются, поэтому их компаратор не может безопасно изменять поведение, если это изменение не согласуется с каждым существующим порядком элементов в наборе». То, что не ясно? – Yakk