Ты можешь добиться желаемого используя частную специализацию, например.
Суть такова. Нужно превратить значения типа перечисления в тип. Сделать мы это можем используя возможность указывать в качестве параметра шаблона значения перечислимых типов.
Например:
enum class AllowedTypes : uint8_t
{
Int8 = 0,
Uint8,
Int16,
Uint16,
};
template< AllowedTypes TYPE >
struct AllowedType;
А для того, чтобы конкретное значение перечисления правильно переводилось в тип, шаблон "AllowedType" нужно специализировать.
spoilertemplate<>
struct AllowedType<AllowedTypes::Int8>
{
using Type = int8_t;
};
template<>
struct AllowedType<AllowedTypes::Uint8>
{
using Type = uint8_t;
};
template<>
struct AllowedType<AllowedTypes::Int16>
{
using Type = int16_t;
};
template<>
struct AllowedType<AllowedTypes::Uint16>
{
using Type = uint16_t;
};
После этого достаточно использовать "typename AllowedType::Type" в нужном тебе месте.
spoilertemplate< AllowedTypes TYPE >
struct spi
{
typename AllowedType<TYPE>::Type* p_tx = nullptr;
constexpr spi() {};
};
Вот пример работы:
spoiler// Example program
#include <typeinfo>
#include <iostream>
#include <string>
#include <cstdint>
enum class AllowedTypes : uint8_t
{
Int8 = 0,
Uint8,
Int16,
Uint16,
};
template< AllowedTypes TYPE >
struct AllowedType;
template<>
struct AllowedType<AllowedTypes::Int8>
{
using Type = int8_t;
};
template<>
struct AllowedType<AllowedTypes::Uint8>
{
using Type = uint8_t;
};
template<>
struct AllowedType<AllowedTypes::Int16>
{
using Type = int16_t;
};
template<>
struct AllowedType<AllowedTypes::Uint16>
{
using Type = uint16_t;
};
template< AllowedTypes TYPE >
using TypeFor = typename AllowedType<TYPE>::Type;
template< AllowedTypes TYPE >
struct spi
{
TypeFor<TYPE>* p_tx = nullptr;
constexpr spi() {};
};
int main()
{
spi<AllowedTypes::Int8> spi1;
std::cout << typeid( *spi1.p_tx ).name() << " " << sizeof( *spi1.p_tx ) << std::endl;
spi<AllowedTypes::Uint16> spi2;
std::cout << typeid( *spi2.p_tx ).name() << " " << sizeof( *spi2.p_tx ) << std::endl;
return 0;
}
cpp.sh/85p6