Портативно поддерживает расслабленный диапазон для петли

C ++ 17 будет (вероятно) ослабить определение диапазона для цикла, позволяющий end() чтобы возвратить отдельный тип (например, страж):

struct MyRange {
struct Sentinel {};
int* begin();
Sentinel end();
};
bool operator!=(int*, MyRange::Sentinel);

На данный момент единственными компиляторами, поддерживающими это, являются gcc 6.1 и clang 4.0+ (пример) (пример сообщения об ошибке). Если я пишу тип диапазона, где сторож был бы более эффективным для конечного типа, как я могу определить, поддерживает ли компилятор ослабленный диапазон? Я не вижу никакого обсуждения этого в P0184R0 (ссылка выше); будет ли предоставлен макрос тестирования функции?

Дальнейшие вопросы:

  • Если есть способ обнаружить поддержку компилятора, безопасно (для библиотеки) изменить тип возвращаемого значения моего end() функция-член? Мне нужно, например, сделать моего стража неявно конвертируемым в мой тип итератора?
  • И наоборот, для компиляторов до C ++ 17 стоит выставлять моего стража под другим именем (например, sentinel())? Могут ли эффективно использовать алгоритмы до C ++ 17 [begin(), sentinel()) или это не стоит дополнительного кода?

1

Решение

в P0096R3, Вы можете проверить, __cpp_range_based_fo‌​r больше или равно 201603. Конечно, Visual Studio не поддерживает любой из макроса функционального теста, так что вам придется проверять его версии отдельно. Они поставили поддержку для него в VS2015 Update 3, но наряду с большинством других поддержки C ++ 17, вы должны использовать /std:c++latest переключатель.

3

Другие решения

Причина, по которой дозорные эффективны, редко связана с внутренним состоянием стража.

Так что один из подходов — дать Sentinel достаточно внутреннего состояния, чтобы сгенерировать версию самого итератора.

Даже в C ++ 14 с единообразным началом for(:) циклы и алгоритмы, которые настаивают на идентичных типах итераторов начала / конца, рукописные алгоритмы или циклы могут использовать ваш дозорный и повысить эффективность.

Библиотека как Boost.Config Обычно это лучшая ставка, если вы хотите получить максимальный охват, но набор функций обнаружения C ++ 17 не был опубликован на эту дату (что я могу найти).

Насколько я могу судить, СФИНАЕ не существует способа обнаружить существование for(:) циклы, которые принимают разные типы начала / конца итератора. (Я мог представить что-то constexpr нет, кроме того, что что-то взломано, но это не в моем умении

Обнаружение, если <algorithms> принять итераторы конца дозорного, вероятно, можно с помощью SFINAE. Но я не уверен, даже если C ++ 17 имеет дозорный <algorithms> или даже собирается; range-v3 должен справиться с переделкой этого.

2

По вопросам рекламы [email protected]