Время компиляции "напротив" std :: less? - PullRequest
0 голосов
/ 14 ноября 2018

Извиняюсь заранее.У меня возникают трудности с поиском правильной формулировки для этого вопроса ...

В качестве упражнения я работаю над очередью с фиксированным приоритетом, которая выбрасывает объекты, превышающие максимальное значение (дляочередь, находящая самый маленький объект X) и выбрасывает объекты меньше чем мин (для очереди, содержащей самые большие объекты X).Вопрос в том, существует ли способ достижения логической «противоположности» компаратора во время компиляции.

См. Закомментированную строку в коде ниже:

template <
    typename T, 
    typename Container = std::vector<T>, 
    typename Compare = std::less<typename Container::value_type>>
class fixed_size_priority_queue : public std::priority_queue<T, Container, Compare>
{
    typename Container::size_type maxSize;
    using base = std::priority_queue<T, Container, Compare>;

  public:
    fixed_size_priority_queue(std::size_t size) : base(), maxSize(size)
    {
        base::c.reserve(size);
    }
    void push(T value)
    {
        if (base::size() < maxSize)
        {
            base::push(value);
        }
        // is there some way of arriving at compile-time opposite of 'comp'?
        else if (!base::comp(base::top(), value))
        {
            while (base::size() >= maxSize)
            {
                base::pop();
            }
            base::push(value);
        }
    }
};

void test_fixedPriQueue()
{

    using smallestInts = fixed_size_priority_queue<int>;
    smallestInts fq(4);
    fq.push(5);
    fq.push(3);
    fq.push(5);
    fq.push(5);
    fq.push(7);
    fq.push(11);
    fq.push(1);
    fq.push(2);
}

int main(int argc, char const *argv[])
{
    test_fixedPriQueue();
    return 0;
}

Я простоиспользовал оператор not (!), чтобы выполнить работу, но повлечет ли это за собой, хотя и очень маленькие, затраты времени выполнения?Есть ли способ достичь std::greater_equal, когда мой класс использует Compare = std::less?

Я надеялся использовать что-то вроде std::not<Compare>, которое разрешило бы до std::greater_equal, когда параметр шаблона Compare равен std::less.Имеет ли это смысл?

** edit **

Попытка предложения от sergeyA дала то, что я искал:

template<typename T, typename Comparison>
struct logical_opposite
{
    using op = void;
};

template <typename T>
struct logical_opposite<T, std::less<T>>
{
    using op = std::greater_equal<T>;
};

template <typename T>
struct logical_opposite<T, std::greater<T>>
{
    using op = std::less_equal<T>;
};

Затем в классе, полученном из priority_queue, создайте экземпляр объекта с логической противоположностью и используйте его при добавлении в очередь:

//...
typename logical_opposite<T, Compare>::op not_comp;

public:
fixed_size_priority_queue(std::size_t size) : base(), maxSize(size), not_comp()
//....

Между типами функторов сравнения существует логическая связь, и я надеялся, что эта связь была выражена в STL.

1 Ответ

0 голосов
/ 14 ноября 2018

Нет видимой разницы между !< и >= на примитивных типах, поэтому ваш страх перед затратами времени выполнения необоснован.

C ++ не является сборкой. Он описывает поведение абстрактной машины. Компиляторы сопоставляют это со сборкой, и операции, которые не имеют заметных различий, могут быть реализованы идентично в сборке.

Хотя для изучения того, что «наблюдаемо» в C ++, требуется некоторый опыт, общее правило состоит в том, чтобы писать чистый код, который позволяет избежать выделения ресурсов, когда это целесообразно, сохранять непрерывность и поддерживать скорость записи O-обозначений, а затем тестировать программы на предмет проблем с производительностью. беспокоиться о других вопросах.

!< против >= не является проблемой «избегать преждевременной пессимизации», поэтому вы должны игнорировать ее, если не найдете код при профилировании.

...