Skip to content

Instantly share code, notes, and snippets.

@leocelente
Last active August 23, 2021 18:09
Show Gist options
  • Save leocelente/c671e7fc8f63f985dea066208776c36d to your computer and use it in GitHub Desktop.
Save leocelente/c671e7fc8f63f985dea066208776c36d to your computer and use it in GitHub Desktop.
Snippets de C++ com várias abstrações - RAII, SFINAE - que compilam com custo zero em assembly; https://godbolt.org/z/31eh1q
// Compilar com o Compiler-Explorer -O1
// https://godbolt.org/z/31eh1q
#include <type_traits>
/* BIBLIOTECA GENERICA*/
template <class Lambda, class FunctorOpen, class FunctorClose, class... Args>
constexpr void wrap(Lambda l, FunctorOpen i, FunctorClose f, Args... p) {
i(p...);
l();
f(p...);
}
template <class Lambda, class Functor, class... Args> // Variadic Template
constexpr void sandwich(Lambda l, Functor f, Args... p) {
wrap(l, f, f, p...);
}
//------------------------------------------
/* BIBLIOTECA DO MICROCONTROLADOR
Tudo que mudaria de um micro pra outro seria a interface dessa `toogle_pin`
e os tipos dos `value` tem que bater com ela */
extern void toggle_pin(int* port, unsigned int pin);
struct Port {
int* value;
};
struct Pin {
unsigned int value;
};
// Restringe que Type tem que ser Port
template <class Type>
using MustBePort =
std::enable_if_t<std::is_same<Type, Port>::value>; // Template
// Metaprogramming
// Restringe que Type tem que ser Pin
template <class Type>
using MustBePin =
std::enable_if_t<std::is_same<Type, Pin>::value>; // Template
// Metaprogramming
template <class PortType, class PinType, class Lambda,
typename = MustBePort<PortType>, // SFINAE
typename = MustBePin<PinType> // SFINAE
>
constexpr void toggle_hold(const PortType port, const PinType pin, Lambda l) {
sandwich(
/* Bloco de Código */ l,
/* Envolvido por */ toggle_pin,
/* Com argumentos */ port.value, pin.value);
}
extern void open_resource(void*);
extern void close_resource(void*);
extern void use_resource(void*);
// RAII
class ResourceHandler {
int* ptr;
public:
int* const get() const{
return ptr;
}
ResourceHandler(int* p) : ptr(p) { open_resource(ptr); }
~ResourceHandler() { close_resource(ptr); }
// Copy, Move ctors auto deleted
};
//-----------------------------------------
/* CODIGO NA APLICAÇAO */
extern void SPI_Transmit(void);
int main() {
ResourceHandler hdlr{nullptr};
constexpr Port peripheral_port{nullptr};
constexpr Pin peripheral_pin{3u};
/* Garante duas chamadas do toggle_pin
Garante que port e pin não sejam trocados */
toggle_hold(peripheral_port, peripheral_pin, [&] {
SPI_Transmit();
SPI_Transmit();
// ...
SPI_Transmit();
});
/* NÃO COMPILA */
// toggle_hold(peripheral_pin, peripheral_port, [&]{
// SPI_Transmit();
// });
/* Compila :( */
// int pin = 3;
// int port = 0;
// toggle_pin((int*)pin, port); /* se fosse toggle_pin(int,int) não precisaria do cast */
// SPI_Transmit();
// SPI_Transmit();
// ...
use_resource(hdlr.get());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment