I have a simple scene in C++ code.
I want to get a long string containing some repeated std::string_view
; is there a way to achieve this without copying the string?
#include <cstdio>
#include <string_view>
struct Logger {
static inline constexpr std::string_view indent = " ";
static inline int level = 0;
Logger() {
level++;
}
// ...
void log(const std::string &msg) {
std::printf(/* repeat indent 'level' times */);
}
};
std::printf
allows you to dynamically specify the field width. For example:
#include <cstdio>
int main() {
int indent_length = 4;
int indent_depth = 3;
// note: "" is passed as an argument for %s
std::printf("%*shi!", indent_length * indent_depth, "");
}
This will output:
hi!
We can use this trick because indentation always consist of one character, so we don't really have to repeat a full std::string_view
.
Obviously, this wouldn't work if you wanted indentation that is a mixture of multiple characters, but that would be highly unusual.
However, that is a very C-style solution, and you could just use a loop to avoid copying:
void log(std::string_view msg) {
for (int i = 0; i < level; ++i) {
std::cout << indent;
}
std::cout << msg;
}
However, if the indent is not a mixture of different characters,
we can do a similar trick using std::cout
as above to avoid this loop:
void log(std::string_view msg) {
std::cout << std::setw(indent_length * level) << "" << msg;
}
If you absolutely insist on using std::printf
, we can still do:
// if msg is always null-terminated
std::printf("%s", msg.data());
// otherwise
std::printf("%.*s", int(msg.length()), msg.data());
Your indent
string can be printed exactly the same way.