std::back_inserter и std::inserter
Есть такой код:
auto sym_draw = [&](u32 ch)
{
//...
};
u32string tmp;
utf8::utf8to32(text.begin(), text.end(), back_inserter(tmp));
for (auto ch : tmp)
{
sym_draw(ch);
}
Всё бы хорошо, но вот tmp строка не нужна, нужны только сами символы.
Чем мне заменить инсертер от стд чтобы символы напрямую шли в лямбду?
Ответы (2 шт):
Ну, попробуйте сделать свой простенький итератор. Мне не хочется скачивать и устанавливать utf8, так что я на примере обычного copy, ладно?
Что-то вроде такого - нечто, что в состоянии получать значение и передавать его функтору (у вас - получать u32 и передавать sym_draw):
using namespace std;
class int_iterator
{
public:
int_iterator(function<void(int)> f):f(f){}
int_iterator& operator++() { return *this; }
int_iterator& operator*() { return *this; }
int_iterator& operator=(int x) { f(x); return *this; }
private:
function<void(int)> f;
};
int main()
{
vector<int> v = {1,2,3,4,5,6,7};
auto f = [](int z) { cout << z*z << " ";};
copy(v.begin(),v.end(),int_iterator(f));
}
Полностью посмотреть можно здесь: https://rextester.com/NRLPB23442
Шаблонизировать несложно, но больше писать нужно... :(
Если разобраться как устроена utf8::utf8to32 то можно её заменить итерацией с помощью utf8::next:
#include <iostream>
#include <utf8.h>
template <typename F>
void for_each_char(const std::string &s, F f) {
auto end = s.end();
for (auto it = s.begin(); it != end; ) {
f(utf8::next(it, end));
}
}
int main() {
auto show = [](char32_t c) {
std::cout << c << ' ';
};
std::string text = "abcd";
for_each_char(text, show);
std::cout << '\n';
}
Можн написать итератор для вывода значений. Немного сложнее, но для разминки можно так:
#include <iostream>
#include <utf8.h>
template <typename F>
class OutputIt {
public:
OutputIt(F f) : f(f) {}
OutputIt &operator ++(int) { return *this; }
OutputIt &operator *() { return *this; }
void operator =(utf8::uint32_t c) { f(c); }
private:
F f;
};
template <typename F>
OutputIt<F> make_output_it(F f) {
return f;
}
int main() {
auto show = [](char32_t c) {
std::cout << c << ' ';
};
std::string text = "abcd";
utf8::utf8to32(text.begin(), text.end(), make_output_it(show));
std::cout << '\n';
}
Оба варианта имеют свои сильные и слабые стороны. Первый проще и компактней. Второй универсальнее: его можно применять с любым алгоритмом, который принимает, например, back_inserter.