2015-09-10 8 views
3

Итак, у меня есть простой кодМожно ли хранить QColor в QMap как ключевой

QMap<QColor, int> colors; 
for(int w = 0; w < image.width(); ++w) 
    for (int h = 0; h < image.height(); ++h) 
     colors[QColor::fromRgb(image.pixel(w,h))]++; 

Сообщение об ошибке

не подходит для «оператора <» (тип операнда «Const QColor 'и' const QColor ').

Так, qMapLessThanKey пытается безуспешно инстанцирует компаратор двух цветов, и это невозможно.

Вопрос: Возможно ли хранить QColor в QMap в качестве значения, а не по ссылке?

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

+0

Это не является исключением в Qt, но вопрос о классе дизайна QColor. Карта не может работать без оператора <, как указывает Джефффри. Это просто, что std :: map является «более гибким» в строительстве. – Gombat

+0

@ Gombat, почему вы думаете, что это вопрос дизайна QColor, но не QMap? Правильно, что мы не можем сравнивать цвета. И очевидно, что часто нам нужно, чтобы сбор значений ключей сортировался по значению, а не по ключу. Я не могу понять причину такой реализации. – cassandrad

+0

Сбор ключевых значений должен быть отсортирован по ключу, чтобы быстро найти пару ключевых значений. Без сравнения ключей поиск двоичного дерева не будет работать. – Gombat

ответ

5

Нет, потому что QColor doesn't provide operator<, который required по QMap «s Key Тип:

Ключ тип QMap должен предоставить operator<() указания общего порядка.

Опция будет определять operator< для QColor себя, но я бы не советовал, так как я не уверен, что он должен быть определен.

Я бы рекомендовал просто использовать std::map с пользовательским компаратором (третий шаблон аргумент) по линиям:

struct color_compare { 
    bool operator()(QColor const&, QColor const&) { /* ... */ } 
}; 

std::map<QColor, Value, color_compare> map; 
// ... 
+0

К сожалению, я использую QMap, а не std :: map, и нет способа передать компаратор в конструктор.Вопрос в том, что это плохой дизайн QMap или есть еще одна подходящая коллекция для хранения ключевого значения и быстрый способ обновления значения. – cassandrad

+0

@cassandradied Это невозможно, если вы не определяете 'operator <' для 'QColor' самостоятельно. Почему вы не можете использовать 'std :: map' точно? – Shoe

+0

Я могу. Для меня просто неожиданно, что в QT есть некоторая коллекция, которая ограничивает тип, который он может хранить. – cassandrad

1

Конечно, это возможно. Это недостающая функция Qt. Вы можете реализовать оператор сравнения себя, сравнивая значения R, G, B, A лексически:

// https://github.com/KubaO/stackoverflown/tree/master/questions/qmap-qcolor-32512125 
#include <QtGui> 

bool operator<(const QColor & a, const QColor & b) { 
    return a.redF() < b.redF() 
     || a.greenF() < b.greenF() 
     || a.blueF() < b.blueF() 
     || a.alphaF() < b.alphaF(); 
} 

int main() { 
    Q_ASSERT(QColor(Qt::blue) < QColor(Qt::red)); 
    Q_ASSERT(QColor(Qt::green) < QColor(Qt::red)); 
    Q_ASSERT(QColor(Qt::blue) < QColor(Qt::green)); 
    Q_ASSERT(! (QColor(Qt::red) < QColor(Qt::red))); 
    QMap<QColor, int> map; 
    map.insert(Qt::red, 0); 
    map.insert(Qt::green, 1); 
    map.insert(Qt::blue, 2); 
    Q_ASSERT(map.size() == 3); 
    Q_ASSERT(map.cbegin().key() == Qt::red); 
    Q_ASSERT((map.cbegin()+1).key() == Qt::green); 
    Q_ASSERT((map.cbegin()+2).key() == Qt::blue); 
} 
+1

Это нелогично сравнивать цвета. Почему Qt :: blue меньше Qt :: red? – cassandrad

+0

@cassandradied Почему бы и нет? Все, что требует «QMap», - это частичный порядок ключа. Определенный нами оператор обеспечивает такой частичный порядок. Вот и все. Вы можете определить ** любое частичное упорядочение ** по заданному типу ключа, независимо от того, имеет ли он смысл ». Это должен быть [частичный заказ] (https://en.wikipedia.org/wiki/Partially_ordered_set), и все. –