Pavel V. 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Компилирую следующий код: template<uint32_t pin> class Pin { public: void Test() { if(pin < 16) { 1: g_test &= ~(0x03UL << (pin * 2)); } else { g_test &= ~(0x03UL << ((pin - 16) * 2)); } } }; int main() { Pin<22> test; test.Test(); } На строчку 1 компилятор ругается: source/main.cpp: In member function 'void Pin<pin>::Test() [with long unsigned int pin = 22ul]': source/main.cpp:30:12: instantiated from here source/main.cpp:18:4: warning: left shift count >= width of type [enabled by default] Код компилируется и работает правильно. Оптимизатор, естественно, выкидывает ненужный код, т.к. pin константа (что видно по листингу). Как убрать это сообщение? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба А g_test - это кто? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Для этого можно использовать частичную специализацию шаблонов. Завести дополнительную шаблонный класс, вычисляющий нужную маску и сделать для него две специализации, для pin < 16 и для pin >= 16. template<uint32_t pin> class Pin { // warning: brain-compiled code ahead template<bool pinLessThen16> struct Mask { enum {value = ~(0x03UL << (pin * 2)) }; }; template<> struct Mask<false> { enum {value = ~(0x03UL << ((pin - 16) * 2)) }; }; public: void Test() { g_test &= Mask<(pin < 16)>::value; } }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pavel V. 0 11 февраля, 2012 Опубликовано 11 февраля, 2012 · Жалоба Для этого можно использовать частичную специализацию шаблонов. Завести дополнительную шаблонный класс, вычисляющий нужную маску и сделать для него две специализации, для pin < 16 и для pin >= 16. Спасибо за идею! В итоге так и сделал, только использовал анонимный параметр, что избавило от необходимости в вызове писать условие pin < 16. Специализацию шаблона нельзя выполнять внутри класса, поэтому вынес наружу. namespace IO { template<uint32_t pin, bool = (pin < 16)> struct ConfigurationMask { static inline uint32_t Clear() { return ~(0x03UL << (pin * 2)); } static inline uint32_t SelSet(Configuration configuration) { return (((uint32_t)configuration >> 4) & 0x03UL) << (pin * 2); } static inline uint32_t ModeSet(Configuration configuration) { return (((uint32_t)configuration >> 2) & 0x03UL) << (pin * 2); } }; template<uint32_t pin> struct ConfigurationMask<pin, false> { static inline uint32_t Clear() { return ~(0x03UL << ((pin - 16) * 2)); } static inline uint32_t SelSet(Configuration configuration) { return (((uint32_t)configuration >> 4) & 0x03UL) << ((pin - 16) * 2); } static inline uint32_t ModeSet(Configuration configuration) { return (((uint32_t)configuration >> 2) & 0x03UL) << ((pin - 16) * 2); } }; template<Port port, uint32_t pin, ActiveState activestate> class Pin { static_assert((pin < 32), "Pin number must be <= 31"); public: /* * Set Configuration */ static void SetConfiguration(Configuration configuration) { ... SEL0 &= ConfigurationMask<pin>::Clear(); SEL0 |= ConfigurationMask<pin>::SelSet(configuration); MODE0 &= ConfigurationMask<pin>::Clear(); MODE0 |= ConfigurationMask<pin>::ModeSet(configuration); ... } }; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 12 февраля, 2012 Опубликовано 12 февраля, 2012 · Жалоба SEL0 &= ConfigurationMask<pin>::Clear(); SEL0 |= ConfigurationMask<pin>::SelSet(configuration); MODE0 &= ConfigurationMask<pin>::Clear(); MODE0 |= ConfigurationMask<pin>::ModeSet(configuration); LPC17 ? Тоже наткнулся на такую заразу со сдвигами («больше ширины» либо «сдвиг на отрицательное значение» в зависимости от константы и ветки if (shift < 32)). if (shift < 32) { LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & ~(0x03 << shift)) | (CLKPWR_PCLKSEL_CCLK_DIV_1 << shift); } else { LPC_SC->PCLKSEL1 = (LPC_SC->PCLKSEL1 & ~(0x03 << (shift-32))) | (CLKPWR_PCLKSEL_CCLK_DIV_1 << (shift-32)); } Сначала по-быстрячку сделал shift локальной переменной функции. Оптимизатор всё делает нормально, а предупреждение пропадает. Потом нарисовал такое (в рабочий код ещё не интегрировал, в тесте с ключиком -S всё красиво): #include <stdint.h> template<unsigned width, unsigned position, unsigned reg_bits = 32> struct field_traits { enum { reg_index = position / reg_bits, shift = position % reg_bits, unshifted_mask = (1UL << width) - 1, mask = unshifted_mask << shift }; static unsigned value(unsigned val) { return (val & unshifted_mask) << shift; } static unsigned place(unsigned reg) { return reg & ~mask; } static unsigned insert(unsigned reg, unsigned val) { return place(reg) | value(val); } }; struct params { volatile uint32_t reg0, reg1; }; params p; template<unsigned pin> struct tst { typedef field_traits<2, 2*pin> traits; static void Setup(unsigned v) { #if 1 traits::reg_index == 0 ? p.reg0 = traits::insert(p.reg0,v) : p.reg1 = traits::insert(p.reg1,v); #else // Имея уверенность (или при соответствующем описании целевой структуры) // можно и так: volatile uint32_t *preg = &p.reg0 + traits::reg_index; *preg = traits::insert(*preg,v); #endif } }; typedef tst<1> tst1; typedef tst<15> tst15; typedef tst<16> tst16; typedef tst<18> tst18; typedef tst<31> tst31; void foo1() { tst1::Setup(0); } void foo15() { tst15::Setup(1); } void foo16() { tst16::Setup(2); } void foo18() { tst18::Setup(2); tst18::Setup(1);} void foo31() { tst31::Setup(3); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pavel V. 0 12 февраля, 2012 Опубликовано 12 февраля, 2012 · Жалоба LPC17 ? Тоже наткнулся на такую заразу со сдвигами («больше ширины» либо «сдвиг на отрицательное значение» в зависимости от константы и ветки if (shift < 32)). Он самый! :) Сначала по-быстрячку сделал shift локальной переменной функции. Оптимизатор всё делает нормально, а предупреждение пропадает. Потом нарисовал такое (в рабочий код ещё не интегрировал, в тесте с ключиком -S всё красиво): Здорово, такой вариант мне больше нравится :) Попробую использовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться