С++. Как наполнить шаблонный класс разным содержимым
Всем здравствуйте.
Есть шаблон класса
#include <cstdint>
#include <iostream>
struct PORT0{
struct IOCR0 { } ;
struct IOCR4 { } ;
struct IOCR8 { } ;
struct IOCR12 { } ;
};
struct PORT1{
struct IOCR0 { } ;
struct IOCR4 { } ;
struct IOCR8 { } ;
};
template<typename Port, std::uint8_t pinNum>
struct Pin
{
using PortType = Port;
constexpr Pin() = default;
static void SetMode(uint8_t mode){
using IOCR = typename std::conditional<(pinNum < 4), typename PortType::IOCR0,
typename std::conditional<((pinNum >= 4) && (pinNum < 8)), typename PortType::IOCR4,
typename std::conditional<((pinNum >= 8) && (pinNum < 12)), typename PortType::IOCR8,
typename PortType::IOCR12
>::type >::type >::type;
}
};
int main()
{
using LED = Pin<PORT1, 0>;
LED::SetMode(0);
}
Нужно что-бы в зависимости от значения pinNum выбирался разный класс для IOCR, частично получилось реализовать с помощью std::conditional но проблема в том что не во всех передаваемый классах Port есть например PortType::IOCR12, если использовать как показано выше std::conditional, компилятор ругается что нету такого метода в передаваемом классе.
Как можно исключить из компиляции классы если их нету в передаваемом классе? Хотел использовать if constexpr но его можно использовать только в шаблонных функциях. Возможно enable_if поможет, но как это правильно реализовать не знаю.
Буду благодарен за помощь.
Ответы (1 шт):
Ну вот такой вариант будет работать даже в С++11. Хотя тут по идее можно упростить заменив именованные порты на шаблоны вида Port<index> и т.п
#include <cstdint>
#include <iostream>
struct PORT0{
struct IOCR0 { } ;
struct IOCR4 { } ;
struct IOCR8 { } ;
struct IOCR12 { } ;
};
struct PORT1{
struct IOCR0 { } ;
struct IOCR4 { } ;
struct IOCR8 { } ;
};
template<typename x_Port, typename ::std::uint8_t x_pin_num, bool x_enabled = true> class
t_IOCR_Impl;
template<typename x_Port, typename ::std::uint8_t x_pin_num> class
t_IOCR_Impl<x_Port, x_pin_num, (x_pin_num < 4)> final
{
public: using t_Type = typename x_Port::IOCR0;
};
template<typename x_Port, typename ::std::uint8_t x_pin_num> class
t_IOCR_Impl<x_Port, x_pin_num, ((4 <= x_pin_num) && (x_pin_num < 8))> final
{
public: using t_Type = typename x_Port::IOCR4;
};
template<typename x_Port, typename ::std::uint8_t x_pin_num> class
t_IOCR_Impl<x_Port, x_pin_num, ((8 <= x_pin_num) && (x_pin_num < 12))> final
{
public: using t_Type = typename x_Port::IOCR8;
};
template<typename x_Port, typename ::std::uint8_t x_pin_num> using
t_IOCR = typename t_IOCR_Impl<x_Port, x_pin_num>::t_Type;
template<typename Port, std::uint8_t pinNum>
struct Pin
{
using PortType = Port;
constexpr Pin() = default;
static void SetMode(uint8_t mode){
using IOCR = t_IOCR<Port, pinNum>;
}
};
int main()
{
using LED = Pin<PORT1, 0>;
LED::SetMode(0);
}