Example
void f(auto const& x) {
inspect (x) {
i as int => std::cout << "int " << i;
[_,y] is [0,even] => std::cout << "point on y-axis and even y " << y;
[a,b] is [int,int] => std::cout << "2-int tuple " << a << " " << b;
s as std::string => std::cout << "string \"" + s + "\"";
is _ => std::cout << "((no matching value))";
}
}
int main() {
f(42);
f(std::pair{0, 2});
f(std::tuple{1, 2});
f("str");
struct {} foo;
f(foo);
}
int 42
point on y-axis and even y 2
2-int tuple 1 2
istring "str"
((no matching value))
Puzzle
- Can you implement
inspect
function which will applly a pattern matching proposal to output values/types into a given ostream?
void inspect(const auto& value, std::ostream& os); // TODO
int main() {
"inspect"_test = [] {
"empty"_test = [] {
std::stringstream str{};
inspect(std::tuple{}, str);
expect("(...)"sv == str.str());
};
"int, double"_test = [] {
std::stringstream str{};
inspect(std::tuple{1, 2.}, str);
expect("(1, 2)"sv == str.str());
};
"int, double, string"_test = [] {
std::stringstream str{};
inspect(std::tuple{1, 2., "str"}, str);
expect("(int, double, _)"sv == str.str());
};
"int, double, long"_test = [] {
std::stringstream str{};
inspect(std::tuple{1, 2., 3l}, str);
expect("(int, double, _)"sv == str.str());
};
"int, int, int"_test = [] {
std::stringstream str{};
inspect(std::tuple{4, 2, 3}, str);
expect("(int, ...)"sv == str.str());
};
"int"_test = [] {
std::stringstream str{};
inspect(std::tuple{42}, str);
expect("(int, ...)"sv == str.str());
};
"double"_test = [] {
std::stringstream str{};
inspect(std::tuple{42.0}, str);
expect("(...)"sv == str.str());
};
};
}
Solutions
void inspect(const auto& value, std::ostream& os) {
inspect(value) {
[x, y] is [int, double] => os << '(' << x << ", " << y << ')';
is [int, double, _] => os << "(int, double, _)";
is [int, ...] => os << "(int, ...)";
is _ => os << "(...)";
}
}
void inspect(const auto& value, std::ostream& os) {
inspect(value) {
[a, b] as [int, double] => os << "(" << a << ", " << b << ")";
is [int, double, _] => os << "(int, double, _)";
is [int, ...] => os << "(int, ...)" ;
is [...] => os << "(...)";
}
}
void inspect(const auto& value, std::ostream& os) {
inspect(value) {
[a, b] => os << "(" << a << ", " << b << ")";
is [int, double, _] => os << "(int, double, _)";
is [int, ...] => os << "(int, ...)";
_ => os << "(...)";
}
}
void inspect(const auto& value, std::ostream& os) {
inspect (value) {
is [1, 2.] => os << "(1, 2)";
is [1, 2., _] => os << "(int, double, _)";
is [int, ...] => os << "(int, ...)";
is _ => os << "(...)";
}
}
void inspect(const auto& value, std::ostream& os) {
inspect(value) {
[a,b] is [int, double] => os << "(" << a << ", " << b << ")" ;
[a,b,c] is [int, double, _] => os << "(int, double, _)";
[a,b,c] is [int, int, int] => os << "(int, ...)";
[i] is [int] => os << "(int, ...)";
is _ => os << "(...)";
}
}