Info
-
Did you know that C++23 allows extended init-statement with alias-declaration in the for loop?
Example
#include <initializer_list>
#include <iostream>
int main() {
for (using T = int; T e : {1, 2}) {
std::cout << e; // prints 1,2
}
for (struct T { int x; int y; }; T e : {T{1,2}, T{3,4}}) {
std::cout << "{" << e.x << ',' << e.y << '}'; // prints {1,2}{3,4}
}
}
Puzzle
- Can you implement an init-statement for the for loop which will add an anonymous struct {x,y} and an alias declaration T to it?
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (/*TODO*/ : {T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}
int main() {
using namespace boost::ut;
"print"_test = [] {
"empty"_test = [] {
std::stringstream str{};
print(str);
expect(std::string_view{""} == str.str());
};
"single pair"_test = [] {
std::stringstream str{};
print(str, std::pair{1,2});
expect(std::string_view{"{1,2}"} == str.str());
};
"multiple pairs"_test = [] {
std::stringstream str{};
print(str, std::pair{1,3}, std::pair{2, 4});
expect(std::string_view{"{1,3}{2,4}"} == str.str());
};
};
}
Solutions
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (using T = struct { int x; int y; }; const T& e : std::initializer_list<T>{T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}
auto print(std::ostream& os) -> std::ostream& { return os; }
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (using T = struct { int x; int y; }; const T& e : {T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (using T = struct {int x; int y;}; const T & e : std::vector<T>{T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (struct T { int x; int y; }; const auto &e : std::initializer_list<T>{{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}
auto print(std::ostream& os, auto... args) -> std::ostream& {
if constexpr (sizeof...(args) > 0) {
for (using T = struct { int x; int y; }; auto const& e : {T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
}
return os;
}
auto print(std::ostream& os, auto... args) -> std::ostream& {
for (using T = struct { int x; int y;}; T const & e : std::array<T, sizeof ...( args)>{T{args.first, args.second}...}) {
os << '{' << e.x << ',' << e.y << '}';
}
return os;
}