Неявное преобразование в явные bool-типы для сортировки контейнеров?
я играю с новым explicit
для cast-операторов. Если вы пишете что-то вроде
struct Data {
explicit operator string();
};
невозможно случайно преобразовать Data
до string
. Тип данных darget bool
является исключением: в некоторых случаях неявное преобразование разрешено, даже если оно отмечено explicit
-- контекстуальные преобразования. Таким образом, вы можете использовать эти типы данных в элементе if(...)
например:
struct Ok {
explicit operator bool(); // allowed in if(...) anyway
};
в пункте "25.4.(2) Сортировка и связанные с ней операции" кажется, позволяет это для Compare
функтор из стандартные контейнеры как set
как хорошо. Но мои попытки с GCC-4.7.0 терпят неудачу, и я уверен, что это мое неправильное понимание или ошибка в gcc?
#include <set>
struct YesNo { // Return value type of Comperator
int val_;
explicit YesNo(int y) : val_{y} {}
/* explicit */ operator bool() { return val_!=0; }
};
static const YesNo yes{1};
static const YesNo no{0};
struct LessYesNo { // Comperator with special return values
YesNo operator()(int a, int b) const {
return a<b ? yes : no;
}
};
int main() {
std::set<int,LessYesNo> data {2,3,4,1,2};
}
без explicit
до operator bool()
пример компилируется. И мое понимание "25.4.(2) " заключается в том, что это также должно компилироваться С в явные.
я понимаю Std правильно что за set
и explicit
bool
преобразования должны работать? и может быть, это ошибка в gcc, или я понял что-то не так?
2 ответов
мое чтение стандарта немного отличается - раздел 25.4 касается алгоритмов сортировки, а не отсортированных контейнеров; контекст, установленный в 25.4.(1) означает, что свойство объекта сравнения указано в разделе 25.4.(2) применяется к алгоритмам в 25.4, а не к отсортированным контейнерам
1 Все операции в 25.4 имеют две версии: одна, которая принимает объект функции типа Compare и тот, который использует оператор.
2 Сравнивать функция тип объекта (20.8). Возвращаемое значение операция вызова функции, применяемая к объекту типа Compare, когда контекстуально преобразуется в bool (4), дает значение true, если первый аргумент звонка меньше второго, и false в противном случае. Сравнить comp используется для алгоритмов, предполагающих отношение упорядочения. Это предполагается, что comp не будет применять любую непостоянную функцию через разыменованный итератор.
Я не знаю, является ли ваш пример должен работать или нет, но я не думаю, что раздел 25.4 применимо здесь.
быстрый тест с вектором и std:: sort works:
#include <list>
#include <algorithm>
struct YesNo { // Return value type of Comperator
int val_;
explicit YesNo(int y) : val_{y} {}
explicit operator bool() { return val_!=0; }
};
static const YesNo yes{1};
static const YesNo no{0};
struct LessYesNo { // Comperator with special return values
YesNo operator()(int a, int b) const {
return a<b ? yes : no;
}
};
int main() {
std::vector<int> data {2,3,4,1,2};
std::sort(std::begin(data), std::end(data), LessYesNo());
}
изменить:
параметр сравнения ассоциативного контейнера определяется в терминах secion 25.4:
1 ассоциативные контейнеры обеспечивают быстрый поиск данных, основанных на ключах. Библиотека предоставляет четыре основных вида ассоциативных контейнеров: set, multiset, map и multimap.
2 каждый ассоциативный контейнер параметризуется по ключу, и отношение упорядочения сравнивает это индуцирует строгий слабый порядок (25.4) на элементах ключа. Кроме того, map и multimap связывают произвольный тип T с ключом. Объект типа Compare называется объектом сравнения контейнера.
и 23. не имеет никаких других условий для типа сравнения, насколько я могу видеть, поэтому кажется разумным предположить, что тип, удовлетворяющий ограничениям 25.4, в равной степени применимо.
правильно ли я понял Std, что для set также должны работать явные преобразования bool?
это своего рода серая зона спецификации. Возвращаемое значение из функции сравнения должно быть "конвертируемым в bool". Но что это значит в свете explicit operator bool()
непонятно.
например, можно написать std::set
сравнение использования как это:
CompFunc functor;
if(functor(input, currVal))
...
или можно сделать это:
CompFunc functor;
bool test = functor(input, currVal);
if(test)
...
оба этих формально законно в C++11? Без понятия. Очевидно, что второй терпит неудачу, если operator bool()
is explicit
.
Я посмотрел на определение std::shared_ptr
и explicit operator bool()
как хорошо. Он также говорит, что std::shared_ptr
является "конвертируемым в bool" в пункте 2 раздела 20.7.2.2.
поэтому я предполагаю, что вторая версия должны будет осуществляться следующим образом:
CompFunc functor;
bool test = static_cast<bool>(functor(input, currVal));
if(test)
...
тот факт, что это не явно указано в любом месте спецификации означает, что он должен быть подан как отчет о дефекте. Но он, вероятно, также должен быть подан как ошибка GCC/libstdc++.
лично я, чтобы быть в безопасности, я бы не полагался на это.
О Контекстном Преобразовании
в пункте 3 раздела 4 говорится:
выражение e, появляющееся в таком контексте, считается контекстуально преобразованным в bool и хорошо сформировано, если и только если объявление bool t (e); хорошо сформирован, для некоторой изобретенной временной переменной t
так операции, "контекстуально конвертируемых в bool" означает, что explicit operator bool()
будет работать. С std::set
"S" Compare " функтор должен подпадать под требования 25.4, и эти требования включают в себя "контекстно преобразованный в bool", он выглядит как ошибка GCC/libstdc++.
Я бы все равно избегал этого, когда вы можете помочь.