struct a { template <typename t> static void f () {}; //Шаблонная статическая функция }; template <typename t> //Шаблон, который я позже хочу параметризовать структурой a. struct b { static void f () { t:: template f<int> (); // ошибки теперь нет - ключевое слово template
struct a { template <typename t> static void f () {}; //Шаблонная статическая функция }; template <typename t> //Шаблон, который я позже хочу параметризовать структурой a. struct b { static void f () { t:: template f<int> (); // ошибки теперь нет - ключевое слово template
} };
Гениально! Пошёл проверять. Если это так, то, коллега, вы спасли мне день, спасибо! UPD: Ура, заработало! А то я вроде и погуглил, и даже нашёл пару упоминаний, что так действительно нельзя. А стандарта под рукой нет, да и пока там найдёшь нужное, с ума свернёшься...
boobonick писал(а):Подскажите, пожалуйста, а есть ли такая конструкция, которая позволяет реализовать вот такое
Смотря в каком языке. Добро пожаловать в C++. В C, конечно, нет. Максимум, что можно в C -- сделать член структуры, являющийся указателем на функцию, но это потребует места под указатель в каждой структуре.
ellioh писал(а):Максимум, что можно в C -- сделать член структуры, являющийся указателем на функцию, но это потребует места под указатель в каждой структуре.
а в С++ разве не так? динамический экземпляр класса вообще почти сплошняком из указателей на методы-функции состоит. а с т.з. пользователя все однофигственно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
В применении, которое нужно вопрошающему (как я это понял), по объёму в С++ будет хуже. Тут есть N структур-описателей, у каждой уникальная функция, указатель на которую в теле структуры. Итого расходов на позицию -- один указатель.
В С++ с виртуальными функциями в структуре будет указатель на VMT -- таблицу указателей на виртуальные функции. Итого расходов на позицию -- указатель на VMT, указатель на функцию в самой VMT плюс какие-то доп. расходы на «служебную» информацию в VMT (у avr-gcc, если правильно помню, добавление в класс первой виртуальнйо функции отжирает 6 байт ОЗУ). А, например, avr-gcc ещё и в ОЗУ хранит саму VMT, хотя мог бы и во флеше, по скорости проигрыш совсем незначтельный, а ОЗУ зря не занималось бы.
Это если будет несколько экземпляров структуры одного типа (т.е. с одинаковой функцией-обработчиком, только данные у каждой свои), и/или ещё и функция не одна, то тогда VMT выручает по объёму сильно. Собственно, и в С такой «закат солнца вручную» можно организовать. Собственно, С++ «без шаблонов» и появился как автоматизатор этих танцев с указателями на функции, которые в С давно и применялись в том числе и для «объектного» подхода. За что ему и спасибо.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
И не верьте тому, кто скажет, что нужно писать { "...", 0, &menu_0_func} и (*punkt_menu[1].function)(222); По стандарту С это совершенно не обязательно. Но если Вам будет приятно -- пишите.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
А... Вот в чём дело, "пункт меню". Я-то поначалу, увидев откровенно C++'ные конструкции, заподозрил, что функция у всех одна, ан нет, нужна именно виртуальность -- вызвать действие, соответствующее пункту меню. Тогда да, указатель на функцию дело решает, совет avreal -- в точку. И для случая, когда виртуальная функция в классе одна, это будет даже эффективнее, чем в C++ (правда, никто не запрещает и в C++ сделать "как в C" с той же эффективностью). Выигрыш по памяти от выноса указателей на виртуальные функции в таблицу, как это делается в C++, начинается, когда этих функций хотя бы две.
Последний раз редактировалось ellioh Вс май 01, 2011 16:33:12, всего редактировалось 1 раз.
Да, спасибо! Так и сделал, через указатель на функцию, просто в моем понимании было, что структура - просто набор разнотипных данных, я и не подозревал, что можно в структуре указатель на функцию сделать
Особенно учитывая то, что лежит в основе «неймановской» архитектуры -- принцип «программа есть данные».
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
int key = get_key(); // получили код всех нажатых кнопок switch(key){ case KEY1: // нажата первая кнопка break; case KEY2: // нажата вторая кнопка break; case KEY1 | KEY2: // нажаты обе кнопки сразу break; // и так далее }
естественно, кнопке соответствует один бит в коде.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
ISR макрос описан в заголовочном файле avr/interrupts.h и не надо писать int. И asm ("sei"); то-же не надо. А для разрешения прерываний, в том-же interrupts.h есть функция sei()
Я ещё только учусь:)
правда он должен их перебирать, а зажигается только один
В Вашем последнем листинге есть _Button= Off;, но в основном цикле нету _Button= On; В прерывании таймера то-же закомментирована эта строка.
Она была раскомментирована, иначе бы кнопки вообще не работали.Сохранил неправильно
Если планируете менять значение _Button в прерывании, то объявите переменную так
Вот как раз хотел добраться до функции switch() не разобрался как она работает. Если не трудно покажите синтаксис с командами. Ещё вопрос если нажаты две кнопки то условие с одной уже не должно сработать?
только #define KEY 0x01 естественно, switch будет реагировать на комбинацию, а не на обе кнопки отдельно, хотя и этот вариант можно реализовать, если приспичит... но логически это неверно: комбинация кнопок должна обозначать ДРУГУЮ команду, чем обе кнопки поотдельности. Например, есть кнопка ВЛЕВО и кнопка ВПРАВО. одновременное нажатие, имхо, не должно приводить к перемещению сначала влево, а потом вправо, зато вполне может приводить к ВХОДУ В МЕНЮ
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
ISR(SIG_OVERFLOW0){ tiks++; if ((_Button==Off)&&(tiks>50)){ tiks=0; _Button=On; TCCR0=0x00; } } unsigned char read_key (void){ Pressed=0; Cur_btn = 0; Pressed =(PINB & 0b00011101); if (~Pressed & 0b00000001) Cur_btn = Btn_Rear; if (~Pressed & 0b00010000) Cur_btn= Btn_Down; if (~Pressed & 0b00001000) Cur_btn = Btn_Up; if (~Pressed & 0b00000100) Cur_btn = Btn_Neytral; //---------- if (Cur_btn>0) { _Button=Off; TCNT0=0x00; TCCR0=0x05; if ((Cur_btn == Btn_Down)&&(_Gear>0)&&(_Gear<6)) _Gear--; if ((Cur_btn == Btn_Up) && (_Gear<5)) _Gear++; if (Cur_btn == Btn_Neytral && ( _Gear==2 || _Gear==1 || _Gear==6)) _Gear=0; if ((Cur_btn == Btn_Rear) && ( _Gear==0)) _Gear=6; } return 0; }
while(1){//Begin while if (_Button== On) read_key(); if (Cur_btn>0){ PORTD = Gears[_Gear]; if ((_Gear>0)&&(_Gear<6)){ пауза: PORTD |=0x80; //_delay_ms(5); PORTD &=(0x7F); } } }//end while
почему переменная tiks, точнее её сравнение с числом в прерывании меняет паузу при метке пауза.Неужели прерывание сравнение с числом занимает столько времени процессора?Таймер вроде не должен:) Или опять volatile использовать?
Может немного по быдлокодерски. Смысл программы прочитать клавиатуру, и включить магниты в соответствии с _Gear. И чтоб переключения не происходили слишком часто запускается таймер включающий кнопки(_Button On или Off). Плюс дополнительно нужно при переключении на время включить ещё один магнит. Примерно так.
Код работает, но почему-то затормаживается - при коде