Передача элемента в лямбду по ссылке на const

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

template<typename Iterator>
void solve_world_hunger(Iterator it)
{
auto lambda = [](const decltype(*it)& x){
auto y = x;   // this should work
x = x;        // this should fail
};
}

Компилятору не нравится этот код:

Ошибка: »const« -qualifier не может быть применен к »int&«(Перевод вручную с немецкого)

Тогда я понял, что decltype(*it) это уже ссылка, и, конечно, это не может быть сделано const, Если я удалю constкод компилируется, но я хочу x = x терпеть неудачу.

Давайте на минуту поверим программисту (это я) и избавимся от const и явный &, который удаляется из-за правил свертывания ссылок, в любом случае. Но подождите, это decltype(*it) на самом деле гарантированный быть ссылкой, или я должен добавить явное & быть в безопасности?

Если мы не доверяем программисту, я могу придумать два решения для решения проблемы:

(const typename std::remove_reference<decltype(*it)>::type& x)

(const typename std::iterator_traits<Iterator>::value_type& x)

Вы можете решить для себя, какой из них более уродливым. В идеале я хотел бы получить решение, которое не включает в себя никакого шаблонного метапрограммирования, потому что моя целевая аудитория никогда не слышала об этом раньше. Так:

Вопрос 1: есть decltype(*it)& всегда такой же как decltype(*it)?

Вопрос 2: Как я могу передать элемент по ссылке на const без шаблонного метапрограммирования?

5

Решение

Вопрос 1: нет, требование к InputIterator просто *it может быть преобразовано в T (таблица 72 в разделе «Требования к итераторам»).

Так decltype(*it) может быть, например, const char& для итератора которого value_type является int, Или это может быть int, Или же double,

С помощью iterator_traits не эквивалентно использованию decltypeрешить, какой вы хотите.

По той же причине, auto value = *it; делает не обязательно даст вам переменную с типом значения итератора.

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

Если для типа признаков используется TMP, то нет способа указать «постоянную ссылку на тип значения итератора» без TMP, поскольку iterator_traits является единственным средством доступа к типу значения произвольного итератора.

Если вы хотите, чтобы decltype тогда как насчет этого?

template<typename Iterator>
void solve_world_hunger(Iterator it)
{
const auto ret_type = *it;
auto lambda = [](decltype(ret_type)& x){
auto y = x;   // this should work
x = x;        // this should fail
};
}

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

К сожалению, это разыменовывает итератор дополнительное время. Возможно, вы могли бы написать какой-нибудь умный код, чтобы избежать этого, но умный код оказался бы альтернативной версией remove_referenceследовательно, ТМП.

4

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector