The challenge of truncating a string is that if you operate on the native level, you risk breaking a codepoint in half. And even when you take the codepoint boundaries in consideration, you still risk breaking a grapheme in half.
The u5e library provides an easy way to truncate a text, starting from a target native size and finding the correct boundary.
#include <algorithm>
#include <iostream>
#include <string>
#include <u5e/utf8_string.hpp>
#include <u5e/utf8_string_grapheme_iterator.hpp>
using std::string;
int main(int argc, char** argv) {
string str("Ola\xCC\x81!");
string::const_iterator stri = str.cbegin();
std::advance(stri, 4);
utf8_string::const_iterator u8b(str.begin());
utf8_string::const_iterator u8e(str.end());
utf8_string::const_iterator u8i(stri);
output.append(gb, gi);
std::cout << output.native_string << std::endl;
}