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

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:

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:

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:

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

(((((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