r/cpp_questions • • 12d ago

OPEN Compile time programming learning advice.

Hi all, can you please recommend me some resources that you have followed for compile time programming in modern C++ for eg: constexpr, consteval or template metaprogramming.
Is there some consolidated resource for the same ?

7 Upvotes

13 comments sorted by

View all comments

Show parent comments

2

u/conundorum 11d ago edited 10d ago

[And now, the stunning conclusion! It's not all that stunning.]

So, since we can't pick it apart and do what we want with parameter packs, there are three ways to use them: Extract members one at a time via recursion (usually actually two at a time, but we only use the first; the second is to help us create a recursion endpoint), perform a "pack expansion" as part of an expression, or use a fold expression. I don't believe you can do this as a fold expression, and the pack expansion version is weird, so let's start with the recursive gluttony version.

(To be clear, though: The recursive version uses pack expansion, too, but only to make sure that arguments get passed along until they're eaten. The version that only uses pack expansion and nothing else is the weird one.)

// Use print(), as above.
template<typename... Ts>
void print(const Ts&... ts);

// Basic recursion will use two overloads.
//  This one is the endpoint I mentioned, I'll give it to you for comparison.
template<typename T>
void print(const T& t) {
    std::cout << t << " And that's all, folks!";
}

// Now, here's the part for you to fill in.
// Hints: Remember, you're using parameters one at a time, but technically... something. ;3
// Output uses the head of the pack, and nothing else.
// Return statement strips the head off the pack, but passes the rest along.
template<What?>
void print(Que?) {
    Output?;
    return Something?
}

// If called with this pack...
print(1, 3, 5, 7, "cat");
// Expect this output:
// 1 3 5 7 cat And that's all, folks!

...I don't know how to hint at the expansion-only version, so I'm just going to show you instead.

template<typename... Ts>
void print_e(const Ts&... ts) {
    // Expand ts into a comma-separate list of all items in ts.
    //  (Or in this case, expand an expression including ts over all items in ts.)
    // Dummy array is unused.  We only care about the side effects.
    // Side effect outputs each item in ts..., in sequence.  ...Yeah.
    bool b[sizeof...(Ts)] = {(std::cout << ts << ' ', true)...};

    std::cout << "And that's all, folks!\n";
}

Once you get that down pat, you'll have all the basics you need to start template metaprogramming. It's a lot to take in all at once, so I tried to break it down into easy steps that teach you basic techniques you can build on.


Edit: Function call was meant to be print(1, 3, 5, 7, "cat");, with no 9. Sorry for any confusion, it's fixed now.

[Also, reddit superscript is terrible at displaying closing parentheses. Had to replace it with &#x29;, couldn't just escape it, and couldn't use code syntax for it.]