Q: 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 строка не нужна, нужны только сами символы.
Чем мне заменить инсертер от стд чтобы символы напрямую шли в лямбду?

A: Ну, попробуйте сделать свой простенький итератор. Мне не хочется скачивать и устанавливать 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
Шаблонизировать несложно, но больше писать нужно... :(

A: Если разобраться как устроена 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.
