Ага, я хочу использовать Type Traits - тогда можно вообще пихать в шаблон что-угодно. Главное, чтобы нужные поля присутствовали. Немного искусственно, но хотя бы так:
template <class traitsT> struct UART {
static_assert(::std::is_same_v<traitsT, ::std::decay_t<decltype(traitsT)>>);
inline constexpr static auto Init() noexcept(true) {
constexpr auto const databits_ = traitsT::databits();
constexpr auto const parity_ = traitsT::parity();
constexpr auto const stb_ = traitsT::stb();
using DataBits = ::std::decay_t<decltype(databits_)>;
using Parity = ::std::decay_t<decltype(parity_)>;
using StopBit = ::std::decay_t<decltype(stb_)>;
// LCRH Register
constexpr ::std::uint32_t PEN = (parity_ != Parity::unused) ? 1 << 1 : 0;
constexpr ::std::uint32_t EPS = (parity_ == Parity::even) ? 1 << 2 : 0;
constexpr ::std::uint32_t STP2 = (stb_ == StopBit::_2) ? 1 << 3 : 0;
constexpr ::std::uint32_t WLEN = static_cast<::std::uint32_t>(databits_) << 5;
constexpr ::std::uint32_t SPS = (parity_ == Parity::stick) ? 1 << 7 : 0;
constexpr ::std::uint32_t lcrh = PEN | EPS | STP2 | WLEN | SPS;
return lcrh;
}
};
int main(int, char **) {
struct MyTraits final {
constexpr inline static auto const databits() noexcept(true) { using Result = ::std::uint32_t; return static_cast<Result>(8); }
constexpr inline static auto const parity() noexcept(true) { enum class Result { unused, even, odd, stick }; return Result::odd; }
constexpr inline static auto const stb() noexcept(true) { enum class Result { _1 = 1, _2 = 2 }; return Result::_1; }
};
::std::cout << UART<MyTraits>{}.Init() << ::std::endl;
return 0;
}