ошибка: несовпадающие типы: <function>и <lambda> - PullRequest
0 голосов
/ 19 сентября 2019

Я написал простую функцию, которая дает мне индекс при использовании std::for_each поверх итератора.Функция выглядит следующим образом:

template<typename It, typename I = std::size_t>
void for_each_indexed(It begin,
                      It end,
                      void l(typename std::iterator_traits<It>::value_type, I),
                      I counter = 0) {
    std::for_each(begin, end,
        [&counter, &l](typename std::iterator_traits<It>::value_type value) {
            l(value, counter);
            counter++;
        });
};

Моя проблема заключается в том, что, когда я передаю лямбду в эту функцию, я получаю сообщение об ошибке, подобное следующему:

test.cpp:40:6: error: no matching function for call to ‘for_each_indexed(std::__cxx11::
basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, crossOutChar(
std::__cxx11::string&, char)::<lambda(char, size_t)>)’
     });
      ^
test.cpp:18:6: note: candidate: ‘template<class It, class I> void for_each_indexed(It, 
It, void (*)(typename std::iterator_traits<_Iter>::value_type, I), I)’
 void for_each_indexed(It begin,
      ^~~~~~~~~~~~~~~~
test.cpp:18:6: note:   template argument deduction/substitution failed:
test.cpp:40:6: note:   mismatched types ‘void (*)(typename std::iterator_traits<_Iter>:
:value_type, I)’ and ‘crossOutChar(std::__cxx11::string&, char)::<lambda(char, size_t)’
     });
      ^

Следующие компиляции иработает:

void process(char c, size_t i) {}

void crossOutChar(std::string &s, char c) {
    for_each_indexed(s.begin(), s.end(), process);
}

, но следующее не делает:

void
crossOutChar(std::string &s, char c) {
    auto process = [c, &s](char c2, size_t i) {
      if (c == c2) {
        s[i] = '*';
      }
    };

    for_each_indexed(s.begin(), s.end(), process);
}

В чем здесь может быть ошибка?Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 19 сентября 2019

Захватывающие лямбды нельзя приводить к указателям на функции.Вы можете изменить свою функцию proto на что-то вроде

template<class F, typename It, typename I = std::size_t>
void for_each_indexed(It begin,
                      It end,
                      F &&l,
                      I counter = 0)

. В качестве примечания, интегральные объекты (counter здесь) лучше фиксируются по значению.

0 голосов
/ 19 сентября 2019

Первое: вы не можете привести свое лямбда-выражение к указателю на функцию, потому что оно захватывает.

Для работы с обоими приведенными вами случаями вы должны использовать std::function.Но из-за приведения к std::function у компилятора возникнут проблемы с выводом I, даже если вы установите аргумент по умолчанию.Затем у вас есть несколько вариантов:

Явно установить std::size_t:

std::function<void(typename std::iterator_traits<It>::value_type, std::size_t)> l

Или создать другой аргумент шаблона для функции:

template<typename It, typename F, typename I = std::size_t>
void for_each_indexed(It begin,
                      It end,
                      F&& l,
                      I counter = 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...