I am a long-time C++ developer and have been playing around with Rust recently. I really love the language, but one thing I miss about Rust from C++ is the ability to manipulate and play around with types. The features that really enable this are variadic templates and generic lambdas. I wish Rust would get something like them in the future.
In C++17, the author's issues with trying to do port and pin with different pin types, has a pretty elegant solution in C++.
Here is a toy solution.
#include <iostream>
#include <tuple>
/*
for (port, pin) in &[(P0, 10), (P1, 7), ...] {
port.pin_cnf[pin].write(|w| {
w.input().disconnect();
w.dir().output();
w
});
}
*/
template <typename PinTuple, typename F>
void for_each_port_and_pin(PinTuple& tuple, F f) {
std::apply(
[&](auto&&... p) {
auto apply_pin = [&](auto& t) { std::apply(f, t); };
(apply_pin(p), ...);
},
tuple);
}
struct P0 {
void write(int pin) {
std::cout << "Writing on Port P0, pin " << pin << "\n";
}
};
struct P1 {
void write(int pin) {
std::cout << "Writing on Port P1, pin " << pin << "\n";
}
};
int main() {
auto ports_and_pins =
std::tuple{std::tuple{P0{}, 10}, std::tuple{P1{}, 7}};
for_each_port_and_pin(ports_and_pins,
[](auto& port, int pin) { port.write(pin); });
}
Impressive that you were able to pull it off in C++17 like this (and extra kudos for the live link), but the resulting code (both template and invocation) looks very cryptic - except for the part commented out; that one is much more pleasant to the eye.
They are differently powerful. Rust's macros can let you extend the syntax and do context-free code generation, where as C++ can let you to type-directed code generation. You can do the latter in Rust using trait dispatch, but it's more awkward and less expressive than what C++ has.
In C++17, the author's issues with trying to do port and pin with different pin types, has a pretty elegant solution in C++.
Here is a toy solution.
Runnable godbolt linkhttps://gcc.godbolt.org/z/dcxnTo