Не хочу вас расстраивать, но вы неправильно поняли что такое PA_4.
И тут не ваша вина, а неоднозначного синтаксиса плюсов. GPIO это
всего лишь namespace. А PA_4 это ТИП, являющийся полной
специализацией шаблонного класса TPin . Шаблонный класс пинов. Каждый пин знает на каком порту висит, свой номер и режим.
template<IsGpio GpioT, uint32_t Pin, IsPinMode TPM>
struct TPin {/* */};
Полная специализация
using PA_4 = Tpin<GpioA<>, 4, PinMode::NotDefined>;
// Использование
using LED_PIN = PA_4;
PA_4 pa4;
pa4=1;
LED_PIN::set();
Есть ещё частичная специализация PA4<>
template<typename TPM>
using PA4 = Tpin<GpioA<>, 4, TPM>;
// Использование
using LED_PIN = PA4<PinMode::PushPull_LowSpeed<0>>;
LED_PIN::mode();// Установить режим
Точно так же PinMode это namespace, в котором специализирован полностью и/или частично класс режимов пинов, что сделало из него ТИПы для передачи в качестве параметров шаблонов.
И вот теперь, когда мы пришли к тому, что пин это ТИП и режим это тоже ТИП, то на арену выходит шаблонный класс ConfigList, который в качестве шаблонных параметров принимает список типов. То что на вражеском называется variadic template. Всякие "команды" для этого класса по аналогии тоже делаем ТИПами и вуаля
template <IsConfigListElement... CLE>
class ConfigList
{ /* */ };
А дальше смотрим лекцию как работать со списками типов от Олега Фатхиева и начинаем смутно понимать в какую сторону копать. А потом садимся и храдкодим. Желательно под руководством более опытного джедая.