Общий лямбда-аргумент для std :: pair

Я пытаюсь понять, возможно ли это в общей лямбде C ++ 14, но я не могу найти правильный способ выразить это (или, возможно, это невозможно). Упрощенный пример:

auto confirmOperation = [](auto pr){
  assert(pr.second);
};

Идея состоит в том, что если вы передадите ему std::pair, где second - это bool (например, то, что возвращается из emplace функций), он сможет посмотреть на это bool.

Если бы это был параметр шаблона, я мог бы явно показать pair с типами пары как общие, но я не думаю, что это возможно с лямбда? Таким образом, вместо этого я помечаю весь аргумент как общий, и поэтому компилятор, похоже, не может сделать вывод, что я передаю ему возврат emplace() карты.

Как это сделать?


person johnbakers    schedule 10.06.2016    source источник
comment
Не могли бы вы показать окружающий код (т.е. с включенной картой)?   -  person Smeeheey    schedule 10.06.2016
comment
Что вы здесь просите? auto является универсальным типом, который может представлять pair. Хотите ли вы изменить поведение функции с помощью типов в возвращаемых значениях?   -  person Jonathan Mee    schedule 10.06.2016
comment
Итак, многие люди проголосовали за это и добавили в избранное. Если вы можете прочитать вышеизложенное и объяснить, что, по вашему мнению, говорит OP, не могли бы вы перевести для меня?   -  person Yakk - Adam Nevraumont    schedule 10.06.2016
comment
В опубликованном вами коде нет ничего плохого. Каким образом он не может удовлетворить то, что вам нужно?   -  person Oktalist    schedule 10.06.2016


Ответы (3)


Вы можете ограничить лямбду, используя enable_if:

auto confirmOperation = [](auto pr) ->
    std::enable_if_t<std::is_same<decltype(pr.second), bool>::value> {
  assert(pr.second);
};

Пример.

person ecatmur    schedule 10.06.2016
comment
Вау, это какое-то кунг-фу. - person johnbakers; 10.06.2016
comment
@ecatmur Да, вот почему я тоже использовал decltype(pr.second);) - person Jonathan Mee; 10.06.2016
comment
Хоть и аккуратно, но как это ответ на вопрос ОП? Короче говоря, почему вы думаете, что это именно то, о чем спрашивает ОП? - person Yakk - Adam Nevraumont; 10.06.2016
comment
@Yakk Если у вас есть пояснения по поводу того, что хочет OP, пожалуйста, просветите нас (мой комментарий, похоже, не выполняет свою работу.) В остальном это такой же хороший ответ, как и любой другой. Он также получил печать кунг-фу OP. для чего-то. - person Jonathan Mee; 10.06.2016

Вы можете определить функцию шаблона деталей реализации:

template<typename T>
void lambda_impl(std::pair<T, bool> const &p) {
  assert(p.second);
}

а затем назовите это в своей лямбде как:

auto f = [](auto p) { lambda_impl(p); };

Следующая схема может быть доступна в будущем с появлением Concepts-Lite. Пока работает только на GCC:

auto f = [](std::pair<auto, auto> const &p) { assert(p.second); };

или даже лучше:

auto f = [](std::pair<auto, bool> const &p) { assert(p.second); };

P.S Clang правильно не компилировать это из-за того, что параметры auto не являются частью C ++ 14.

person 101010    schedule 10.06.2016
comment
Это не компилируется на clang с включенным c ++ 14 - person Smeeheey; 10.06.2016
comment
очень красиво, но мой Clang с -std = c ++ 14 не скомпилирует это. он говорит: 'auto' not allowed in template argument и подчеркивает первый auto в pair, который у вас там - person johnbakers; 10.06.2016
comment
Это печально, потому что он компилируется на coliru.stacked-crooked.com/a/288f843d3219dc07 . Это стандарт или расширение GCC? - person KABoissonneault; 10.06.2016
comment
Могу только предположить, что это нестандартное поведение? - person johnbakers; 10.06.2016
comment
Не работает и на MSVS2015 (я не знаю действительно хорошего инструмента для проверки соответствия). - person NathanOliver; 10.06.2016
comment
Из cppreference: если auto используется как тип параметра, лямбда является общей лямбда. . Поскольку auto не является типом параметра, то это не может быть универсальная лямбда. Я думаю, что это отличная функция. - person KABoissonneault; 10.06.2016
comment
@ 101010: «Еще лучше» действительно только с Concepts TS. - person Nicol Bolas; 10.06.2016
comment
@NicolBolas Извините всех, я исправил, что работаю с GCC, и я забыл, что автоматические параметры будут доступны в будущем :) - person 101010; 10.06.2016
comment
@ 101010 Это будет в C ++ 1z? - person NathanOliver; 10.06.2016
comment
@NathanOliver Посмотрите на Concepts TS, который, к сожалению, не является частью C ++ 17 - person KABoissonneault; 10.06.2016
comment
@NathanOliver В прошлый раз, когда я проверял, Херб сказал, что Concepts нужно доработать, чтобы сделать это на C ++ 17 - person 101010; 10.06.2016
comment
Облом. Спасибо за информацию, ребята - person NathanOliver; 10.06.2016
comment
@KABoissonneault Я думал, что Херб Саттер говорил, что если комитет по стандартам разрешит static_if, мы могли бы иметь концепции с C ++ 17, или комитет по стандартам официально отклонил это? - person Jonathan Mee; 10.06.2016

Похоже, вы могли бы просто использовать is_same и _ 2_ здесь:

[](auto pr){
    static_assert(is_same_v<decltype(pr.second), bool>);
    assert(pr.second);
};

Или, если C ++ 17 не является вариантом, требуется сообщение для static_assert, и вы не сможете использовать is_same_v:

[](auto pr){
    static_assert(is_same<decltype(pr.second), bool>::value, "ouch");
    assert(pr.second);
}

Живой пример

person Jonathan Mee    schedule 10.06.2016
comment
Разве static_assert без сообщения только C ++ 17? А что произойдет, если pr.second не является допустимым выражением? - person KABoissonneault; 10.06.2016
comment
@KABoissonneault Вы правы. Я написал живой пример, используя только C ++ 14. Если pr.second недействителен, запускается static_assert. Кажется, что это именно то, что мы хотели в первую очередь? - person Jonathan Mee; 10.06.2016