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::arrayto make a classfixed_string, together withoperator+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 likeconst char[4]) by matching an array-style argument in the constructor or function. Documentation ofstd::arrayprovides several examples in that regard.The first 2 tests are testing whether
fixed_stringworks expectably. To pass these tests, you must name the type exactlyfixed_string, and make sure that the example listed in the section below would work.Typically, the
fixed_stringhas 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+is2and priority of*is3; in turn if someone wants to format a multiplication of two additive expressions1+2and3+4(both with toplevel priority2), the result is formatted correctly as(1+2)*(3+4)(with toplevel priority3), instead of mathematically embarrassing1+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)+3from1+(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
varfor declaring variables,var("abc")should make a variable calledabcthat is formatted simply asabc. The variables are assumed to have AST priority9, so that they don't get unnecessarily parenthesized.To combine the variables, implement
operator+andoperator*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
numsuch thatnum<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
unsignedtype.Both the
fixed_stringand your formatter object should support aconstexprmethod.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,varand the two operators into a single filefixfmt.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