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).
Плюс дополнительно нужно при переключении на время включить ещё один магнит.
Примерно так.
Код работает, но почему-то затормаживается - при коде