I have just started using bits and bobs of C++26 in my experimental code and came across template for. It looks curious and also changes the look and feel of traditional C++ code IMO. So what it is used for? I will take the simplest possible example to explain what I understood about it to focus on the featue and not on the problem.
Let’s look at the following exaple code:
// no_template_for.cpp <iostream>template <int Number> void print_my_number(){ std::cout << "My number = " << Number << "\n";}int main(){ print_my_number<1>(); print_my_number<2>(); print_my_number<3>(); return 0;}
Pretty straightforward, function template print_my_number takes a non-type template parameter of type int and prints it. From main() we call it multiple times and it prints the following on the console:
$ g++ no_template_for.cpp -o no_template_for$ ./no_template_forMy number = 1My number = 2My number = 3
In main() we have a redundancy of calling the same function template over and over and we want to put it in a loop somewhat like the following:
// no_template_for_loop.cpp <array> <iostream>template <int Number> void print_my_number(){ std::cout << "My number = " << Number << "\n";}int main(){ std::array<int, 3> my_number_array{ 1, 2, 3 }; for (int v : my_number_array) { print_my_number<v>(); } return 0;}
However, this code will not compile because the function template instantiation will fail due to the fact that the loop variable v is not usable as the non-type template argument to the print_my_number<>. Because v is runtime loop variable but template substition requires constant expression. Won’t explain it here any further.
Here comes our template for expression handy and you can rewrite the above code in the following way using template for:
// template_for.cpp <array> <iostream>// std::array<int, 3> my_array{ 1, 2, 3 };template <int Number> void print_my_number(){ std::cout << "My number = " << Number << "\n";}int main(){ static constexpr std::array<int, 3> my_array{ 1, 2, 3 }; template for (constexpr int v : my_array) { print_my_number<v>(); } return 0;}
You can compile it as below:
$ g++ --std=c++26 template_for.cpp -o template_for$ ./template_for My number = 1My number = 2My number = 3
Note: I have discussed how to set up C++26 compiler (GCC 16.1) in a previous post.
Remember to declare the array as static constexpr so that both its values and its address are usable during constant evaluation (if you are declaring it within the scope of a function). Alternatively you can declare it global (won’t recommend) so that it’s address is fixed and template instatiation is happy. Or you can put it in a namespace scope and use as below:
// template_for.cpp <array> <iostream>namespace MyNumberSpace{ constexpr std::array<int, 3> my_array{ 1, 2, 3 };}template <int Number> void print_my_number(){ std::cout << "My number = " << Number << "\n";}int main(){ // constexpr std::array<int, 3> my_array{ 1, 2, 3 }; template for (constexpr int v : MyNumberSpace::my_array) { print_my_number<v>(); } return 0;}
template for generates the ncessary instantiation of the print_my_number<> template function using the loop iterator v and that solves our earlier problem.
This was a simple example to just understand the concept of it, hope it was useful. The source code used can be found here.
Leave a Reply