AHTOXA, посмотрел я на ваши труды и попробовал написать подобное для АВР. Сначала было так:
Код
template<GPIO_mode_t mode, char port, int bit, char activestate>
class Pin{
inline volatile uint8_t & PORTx()
{
#if defined (PORTA)
if (port == 'A') return PORTA;
#endif
#if defined (PORTB)
if (port == 'B') return PORTB;
#endif
//..................такая конструкция для буков С..F и все вместе для DDRх и PINх}
inline void On()
{
if ( mode==BIDIR || mode==OUTPUT ) {activestate == 'L' ? PORTx()&=~mask : PORTx()|=mask;}
if ( mode==OUTPUT_OK ) {activestate == 'L' ? DDRx()|=mask : DDRx()&=~mask;}
}
// и тп
}
Потом пытался уменьшить количество писанины в части ссылок на регистры:
Код
template<char port> class Base_Pin;
template<> // такой шаблон для всех буков - можно сделать макрос
class Base_Pin<'A'>
{
public:
inline volatile uint8_t & PORTx(){return PORTA;}
inline volatile uint8_t & DDRx(){return DDRA;}
inline volatile uint8_t & PINx(){return PINA;}
};
template<GPIO_mode_t mode, char port, int bit, char activestate>
class Pin2 : public Base_Pin<port>
{ inline void On(){Base_Pin<port>::PORTx()|=(1<<bit);} };
И если дальше "упрощать" создав макрос для объявления базовых классов всех портов, то приходим к необходимости отказаться от символьных констант и воспользоваться enum-ом. В итоге получаем код Alex312. Но я оставил себе первый вариант. Он хоть и громоздкий, но зато легко читаемый\понимаемый.
И да кстати. Я так и не понял в чем вкусность переопределения операторов в примере Антона.