Format
vix::format provides lightweight placeholder-based string formatting for Vix.
Use it when you want to build strings with simple {} or {0} placeholders without pulling in a large formatting API.
Public header
#include <vix/format.hpp>You can also include the implementation header directly:
#include <vix/format/Format.hpp>What Format provides
The format API provides:
- automatic placeholders with
{} - explicit positional placeholders with
{0},{1},{2} - escaped braces with
{{and}} - formatted output into a new
std::string - appending formatted output to an existing string
- replacing an existing string with formatted output
vix::format_errorfor invalid format strings- integration with the Vix rendering pipeline used by
vix::print
It is intentionally small.
Unsupported on purpose:
{:>10}
{:.2f}
{:x}Format specifiers are not supported.
Basic usage
#include <vix/format.hpp>
#include <vix/print.hpp>
int main()
{
std::string message = vix::format("Hello, {}", "world");
vix::print(message);
return 0;
}Output:
Hello, worldAutomatic placeholders
Use {} to insert arguments in order.
std::string s = vix::format("{} + {} = {}", 2, 3, 5);Result:
2 + 3 = 5Automatic placeholders consume arguments from left to right.
vix::format("Name: {}, age: {}", "Ada", 37);Result:
Name: Ada, age: 37Explicit positional placeholders
Use {0}, {1}, {2} to select arguments by index.
std::string s = vix::format("{0} + {0} = {1}", 2, 4);Result:
2 + 2 = 4Argument indexes are zero-based.
vix::format("first={0}, second={1}", "A", "B");Result:
first=A, second=BReuse arguments
Explicit placeholders can reuse the same argument multiple times.
std::string s = vix::format("{0}/{0}/{1}", "api", "status");Result:
api/api/statusEscaped braces
Use {{ to write a literal {.
Use }} to write a literal }.
std::string s = vix::format("{{ config }} = {}", "ready");Result:
{ config } = readyAutomatic and explicit indexing cannot be mixed
This is invalid:
vix::format("{} {0}", "A");It throws:
vix::format_errorUse only one style per format string.
Good:
vix::format("{} {}", "A", "B");Good:
vix::format("{0} {1}", "A", "B");Bad:
vix::format("{} {1}", "A", "B");Format specifiers are not supported
This is invalid:
vix::format("{:.2f}", 3.14159);It throws:
vix::format_errorUse simple placeholders only:
vix::format("value = {}", 3.14159);format
vix::format(...) returns a new string.
std::string s = vix::format("User {} has id {}", "Ada", 42);Result:
User Ada has id 42Signature:
template <typename... Args>
std::string format(std::string_view fmt, const Args &...args);format_append
vix::format_append(...) appends formatted output to an existing string.
std::string out = "prefix: ";
vix::format_append(out, "{} = {}", "status", "ok");Result:
prefix: status = okSignature:
template <typename... Args>
void format_append(std::string &out, std::string_view fmt, const Args &...args);Use it when you want to build a string incrementally.
std::string out;
vix::format_append(out, "method={}", "GET");
vix::format_append(out, ", path={}", "/api/status");Result:
method=GET, path=/api/statusformat_to
vix::format_to(...) replaces the destination string with formatted output.
std::string out = "old value";
vix::format_to(out, "new value: {}", 42);Result:
new value: 42Signature:
template <typename... Args>
void format_to(std::string &out, std::string_view fmt, const Args &...args);Use it when you want to reuse an existing string object but replace its content.
format_error
vix::format_error is thrown when the format string is invalid or when an argument index is invalid.
try
{
auto s = vix::format("{1}", "only one argument");
}
catch (const vix::format_error &e)
{
vix::print("format error:", e.what());
}Common causes:
- missing argument
- invalid explicit index
- unmatched
{ - single
} - mixed automatic and explicit placeholders
- unsupported format specifier
Missing argument
This is invalid:
vix::format("{} {}", "one");There are two placeholders but only one argument.
It throws:
vix::format_errorInvalid argument index
This is invalid:
vix::format("{2}", "a", "b");Indexes start at 0.
Available indexes are:
0
1Index 2 is out of range.
Unmatched opening brace
This is invalid:
vix::format("Hello {", "world");It throws:
vix::format_errorUse escaped braces if you want a literal brace.
vix::format("Hello { { ");Single closing brace
This is invalid:
vix::format("Hello }");It throws:
vix::format_errorUse }} for a literal closing brace.
vix::format("Hello }}");Supported placeholder syntax
| Syntax | Meaning |
|---|---|
{} | Insert next automatic argument. |
{0} | Insert argument at index 0. |
{1} | Insert argument at index 1. |
{{ | Insert literal {. |
}} | Insert literal }. |
Unsupported syntax
| Syntax | Reason |
|---|---|
{:>10} | Format specifiers are not supported. |
{:.2f} | Format specifiers are not supported. |
{:x} | Format specifiers are not supported. |
{name} | Named placeholders are not supported. |
{} mixed with {0} | Mixed indexing is rejected. |
Formatting strings
vix::format uses the Vix rendering pipeline.
Strings are inserted without extra quotes.
std::string s = vix::format("Hello, {}", std::string{"Ada"});Result:
Hello, AdaThis is different from debug-style printing where strings may be shown with quotes depending on print configuration.
Formatting numbers
std::string s = vix::format("x={}, y={}", 10, 20);Result:
x=10, y=20Formatting booleans
std::string s = vix::format("enabled={}", true);Result:
enabled=trueFormatting containers
Because vix::format uses the Vix rendering pipeline, containers can be formatted too.
#include <vix/format.hpp>
#include <vector>
int main()
{
std::vector<int> values{1, 2, 3};
std::string s = vix::format("values = {}", values);
return 0;
}Result shape:
values = [1, 2, 3]Formatting maps
#include <vix/format.hpp>
#include <map>
#include <string>
int main()
{
std::map<std::string, int> scores{
{"Ada", 10},
{"Bob", 20}
};
std::string s = vix::format("scores = {}", scores);
return 0;
}Result shape:
scores = {Ada => 10, Bob => 20}Formatting optional values
#include <vix/format.hpp>
#include <optional>
int main()
{
std::optional<int> value = 42;
std::string s = vix::format("value = {}", value);
return 0;
}Result:
value = Some(42)Empty optional:
std::optional<int> value;
std::string s = vix::format("value = {}", value);Result:
value = NoneFormatting filesystem paths
#include <vix/format.hpp>
#include <filesystem>
int main()
{
std::filesystem::path path{"public/index.html"};
std::string s = vix::format("file = {}", path);
return 0;
}Result shape:
file = path("public/index.html")Formatting custom types
vix::format uses the same rendering engine as vix::print.
That means custom types can be supported with:
operator<<vix_format(...)ADL hookvix::formatter<T>specialization
Custom type with operator<<
#include <vix/format.hpp>
#include <ostream>
#include <string>
struct User
{
std::string name;
int age;
};
std::ostream &operator<<(std::ostream &os, const User &user)
{
return os << "User{name=" << user.name << ", age=" << user.age << "}";
}
int main()
{
User user{"Ada", 37};
std::string s = vix::format("{}", user);
return 0;
}Result:
User{name=Ada, age=37}Custom type with vix::formatter
#include <vix/format.hpp>
#include <ostream>
#include <string>
struct Point
{
int x;
int y;
};
template <>
struct vix::formatter<Point>
{
static void format(std::ostream &os, const Point &p)
{
os << "Point(" << p.x << ", " << p.y << ")";
}
};
int main()
{
Point p{10, 20};
std::string s = vix::format("position = {}", p);
return 0;
}Result:
position = Point(10, 20)Custom type with ADL vix_format
#include <vix/format.hpp>
#include <ostream>
namespace app
{
struct Color
{
int r;
int g;
int b;
};
void vix_format(std::ostream &os, const Color &color)
{
os << "rgb(" << color.r << ", " << color.g << ", " << color.b << ")";
}
}
int main()
{
app::Color color{255, 128, 0};
std::string s = vix::format("color = {}", color);
return 0;
}Result:
color = rgb(255, 128, 0)Use with Vix HTTP handlers
vix::format is useful inside handlers when building small messages.
#include <vix.hpp>
#include <vix/format.hpp>
int main()
{
vix::App app;
app.get("/users/{id}", [](vix::Request &req, vix::Response &res)
{
const std::string id = req.param("id");
res.text(vix::format("User id: {}", id));
});
app.run(8080);
return 0;
}Request:
GET /users/42Response:
User id: 42Use with logs
#include <vix/format.hpp>
#include <vix/print.hpp>
int main()
{
const std::string method = "GET";
const std::string path = "/api/status";
vix::print(vix::format("{} {}", method, path));
return 0;
}Output:
GET /api/statusBuild strings incrementally
Use format_append(...).
#include <vix/format.hpp>
int main()
{
std::string out;
vix::format_append(out, "method={}", "GET");
vix::format_append(out, " path={}", "/api/status");
vix::format_append(out, " status={}", 200);
return 0;
}Result:
method=GET path=/api/status status=200Replace an existing string
Use format_to(...).
#include <vix/format.hpp>
int main()
{
std::string message = "old";
vix::format_to(message, "status={}", "ok");
return 0;
}Result:
status=okError handling example
#include <vix/format.hpp>
#include <vix/print.hpp>
int main()
{
try
{
std::string s = vix::format("{} {}", "only one argument");
vix::print(s);
}
catch (const vix::format_error &e)
{
vix::print("format error:", e.what());
}
return 0;
}Output shape:
format error: format argument index out of rangeAPI summary
| API | Purpose |
|---|---|
vix::format(fmt, args...) | Return a new formatted string. |
vix::format_append(out, fmt, args...) | Append formatted output to an existing string. |
vix::format_to(out, fmt, args...) | Replace an existing string with formatted output. |
vix::format_error | Exception thrown for invalid format strings or invalid argument access. |
Placeholder summary
| Placeholder | Meaning |
|---|---|
{} | Insert the next automatic argument. |
{0} | Insert argument at index 0. |
{1} | Insert argument at index 1. |
{{ | Insert literal {. |
}} | Insert literal }. |
Error summary
| Invalid input | Error reason |
|---|---|
{ | Unmatched opening brace. |
} | Single closing brace. |
{abc} | Invalid explicit index. |
{:>10} | Format specifiers are not supported. |
{} {0} | Cannot mix automatic and explicit indexing. |
{2} with two arguments | Argument index out of range. |
Best practices
Use {} for simple left-to-right formatting.
vix::format("{} {}", "Hello", "world");Use explicit indexes when reusing arguments.
vix::format("{0} + {0} = {1}", 2, 4);Do not mix {} and {0} in the same format string.
vix::format("{} {}", "A", "B");or:
vix::format("{0} {1}", "A", "B");Use format_append(...) for incremental string building.
vix::format_append(out, "id={}", id);Use format_to(...) when reusing a string object.
vix::format_to(out, "status={}", status);Use vix::formatter<T> or operator<< for custom types.
template <>
struct vix::formatter<MyType>
{
static void format(std::ostream &os, const MyType &value)
{
os << value.name;
}
};Keep formatting simple.
Vix format is intentionally lightweight.
Use it for simple readable strings, not advanced alignment or numeric formatting.Related APIs
| API | Purpose |
|---|---|
vix::print(...) | Print values to stdout. |
vix::sprint(...) | Convert multiple printable values to a string. |
vix::to_string(value) | Convert one printable value to a string. |
vix::write_to(os, value) | Write one value to a stream. |
vix::formatter<T> | Customize rendering for a type. |
Next steps
Read the related pages: