# Zkouška C++ 17. 6. 2026

## String formater

You might have seen a "formatter" for expressions, which is a function that converts a C++-code-styled AST into a nicely formatted, properly parenthesized and very printable string. One might create an object structure such as

```cpp
expression e = (expr_variable("a") + expr_variable("b")) * expr_int(3);
std::println("{}", e.as_string());
```

and expect output such as `(a+b)*3`.

Unfortunately, such tools tend to be based on `std::string` or similar string containers; for a greater purpose of compile-time expression annotators and code generators we would instead wish for one that can be run entirely at compile time (which is somewhat difficult with `std::string`).

Thus, your task is to make code like this work:

```cpp
constexpr auto x = var("hello")+num<31337>;
constexpr auto y = x*var("world")+num<42>;
std::println("{}", y.c_str());
```

which would print out `(hello+31337)*world+42`.

## How-to and details

- You will need a string representation that works at compile time, and supports concatenation. The recommended way is wrapping `std::array` to make a class `fixed_string`, together with `operator+` for concatenating the strings. You will need a way to "import" the data from static string literals such as `"abc"` -- these can be actually matched together with their size (size of `"abc"` is 4, because its type is something like `const char[4]`) by matching an array-style argument in the constructor or function. Documentation of `std::array` provides several examples in that regard.

- The first 2 tests are testing whether `fixed_string` works expectably. To pass these tests, you must name the type exactly `fixed_string`, and make sure that the example listed in the section below would work.

- Typically, the `fixed_string` has a single length-related template argument, which is used as a static dimension for the internal array of values.

- You will need a "formatted string" representation that wraps the `fixed_string`, but also remembers the priority of the last operator that has been applied (the "top" one in the current AST). In our case, priority of `+` is `2` and priority of `*` is `3`; in turn if someone wants to format a multiplication of two additive expressions `1+2` and `3+4` (both with toplevel priority `2`), the result is formatted correctly as `(1+2)*(3+4)` (with toplevel priority `3`), instead of mathematically embarrassing `1+2*3+4`.

- For simplicity, we do not care about operator fixities, and assume each operation is associative. (In realistic situations one might want to distinguish `(1+2)+3` from `1+(2+3)` since such calculation may sometimes yield a different result (with floats!), but we do not care about that.)

- To create the formatted values, you will need a tool called `var` for declaring variables, `var("abc")` should make a variable called `abc` that is formatted simply as `abc`. The variables are assumed to have AST priority `9`, so that they don't get unnecessarily parenthesized.

- To combine the variables, implement `operator+` and `operator*` for your formatter type, with proper treatment of parenthesization. (Note there are 4 different cases.)

- Make sure the system is ready for extension (the users will aim to add more operators).

- To inject numbers, implement `num` such that `num<123>` injects a numeric literal into the formatter. Except for the necessity to have the integers converted to strings, the numbers would behave quite similarly to variable names.

- For simplicity, all accepted numbers will fit the `unsigned` type.

- Both the `fixed_string` and your formatter object should support a `constexpr` method `.c_str()` that returns a pointer to a zero-terminated array of characters, which describes the contents of the (formatted) string.

## Additional testing code

Proper implementation of fixed strings should be able to make this work:

```cpp
constexpr auto x = fixed_string("hello ");
constexpr auto y = fixed_string("world");
constexpr auto xy = x + y;
std::println("{}", xy.c_str());
```

(...prints out `hello world`.)

One should be able make nice expression-printing `constexpr` functions such as this Horner-scheme demonstrator:

```cpp
template <unsigned N> struct binarized_v {
  static constexpr auto value = binarized_v<N / 2>::value * num<2> + num<N % 2>;
};

template <> struct binarized_v<0> {
  static constexpr auto value = num<0>;
};
```

Binarizing value `61` should produce an expression like

```text
(((((0*2+1)*2+1)*2+1)*2+1)*2+0)*2+1
```

## Submission and troubleshooting

- Save your implementations of `fixed_string`, `num`, `var` and the two operators into a single file `fixfmt.hpp`. Only upload that single file.

- If the automated tests keep failing BUT your code provably works on all use-case examples you can think of, ask the examiner for a hint; you will likely get a more advanced example.

- If the above does not solve the problem, add a comment at the end of the file that describes what you have tested and why you think that it should satisfy the tests.

### Nápověda

- https://teaching.mff.cuni.cz/nprg041-web/labtest.en.html
- https://teaching.ms.mff.cuni.cz/nprg051-web
- https://en.cppreference.com/cpp/symbol_index