Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите написать пару макросов 
:(
    Опции темы
newbee
Дата 5.2.2012, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



Мммм и еще раз здравствуйте smile

Друзья, из вашего сумбурного диалога я так и не поняла, поняли ли вы меня... Еще раз: функции OR и AND - не какие-то сферические штуковины со знакомыми названиями! Это аналогия обычных операторов && и ||, которые могут принимать  >=0 параметров (на практике сойдет >=2). Как работает обычный ||: он последовательно вычисляет аргументы и как как только наткнется на истинный результат, возвращает true, OR же вместо true возвращает само это вычисленное значение. Если все аргументы ложны, и ||, и OR возвращают 0.

Обычный &&: последовательно вычисляются аргументы, при встрече первого ложного результата возвращается 0, в AND - аналогично. Если результат вычисления всех аргументов истинен, && возвращает true, AND возвращает последний результат.

mes, у тебя функции неленивые (поправь, если я не права), для AND/OR это недопустимо... В лучшем случае это обернется легко обнаруживаемым сегфолтом, в худшем - сложно уловимыми побочными эффектами. По логике правильно.

volatile, Common Lisp. Не скриптовое, динамически типизированное.

math64, спасибо за помощь, сейчас буду разбираться...

boostcoder, тебе вообще огромное спасибо, сейчас тоже потыкаю твой последний вариант... Я вот сижу смотрю на раскрытие макроса и понимаю, что его аргументы (b1)(b2)(b3) будут вычисляться далеко не один раз... Значит нужно вначале раскрытия генерировать примерно следующее:
Код

typeof(b1) __tmp_1=b1;
typeof(b2) __tmp_2=b2;
typeof(b3) __tmp_3=b3;


И потом внутри мега ?:-конструкции использовать __tmp_X вместо bX. Мне сложно судить наверняка, но при нынешнем однопроходном раскрытии макроса это нереально. И отчасти вдогонку к этому, не мог бы ты объяснить без привязки к BOOST_PP, каким образом препроцессор си раскрывает макрос macro((b1)(b2))? То есть получается, он не просто разбивает входные аргументы, а распарсивает выражение...


--------------------
You're face to face
With man who sold the world
PM   Вверх
boostcoder
Дата 5.2.2012, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(newbee @  5.2.2012,  22:23 Найти цитируемый пост)
(b1)(b2)(b3) будут вычисляться далеко не один раз... Значит нужно вначале раскрытия генерировать примерно следующее:

и выражения перестанут быть ленивыми.

ты это.. протесть то что у меня получилось, чтоб я убедился в том что правильно тебя понял и сделал. потом подумаем над доделками.

Цитата(newbee @  5.2.2012,  22:23 Найти цитируемый пост)
(b1)(b2)

в терминах boost.preprocessor - это последовательность. я же, итерируюсь по последовательности, и на каждой итерации раскрываю часть общего выражения.

Добавлено через 10 минут и 1 секунду
Цитата(newbee @  5.2.2012,  22:23 Найти цитируемый пост)
при нынешнем однопроходном раскрытии макроса это нереально.

можно дважды пройтись по последовательности.
PM WWW   Вверх
volatile
Дата 5.2.2012, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(newbee @  5.2.2012,  22:23 Найти цитируемый пост)
Common Lisp. Не скриптовое, динамически типизированное.

Ну да. динамически типизированное. там это имеет практический смысл.

В С++ даже если и получиться написать (кстати неплохие варианты тут предлагали, ребята постарались!)
но использовать это почти не получится.

Все аргументы должны быть приводимы к одному типу, и кроме того еще и к bool (если я правильно понял..)
Где это можно использовать?
Не, ну можно конечно что-то придумать такое, где такое применить, но это имхо, искусственное притягивание за уши.
На приктике (при статической типизации) это практически бемполезная конструкция, имхо конечно.


Это сообщение отредактировал(а) volatile - 5.2.2012, 23:58
PM MAIL   Вверх
newbee
Дата 6.2.2012, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



boostcoder, я поэксперементировала с твоими вариантами, с точки зрения логики раскрытия все правильно! Ты прав, сразу раскрывать все аргументы нельзя - привет, ленивость! Но нашлась мысля smile Макросы можно разворачивать в ({})-форму, это расширение GCC, тогда на каждой итерации можно сначала вычислить результат, а потом его проверять!
Код
std::cout<<(1?({int res=foo();res?res:-1;}):0)<<std::endl;//просто пример ({})


Цитата(boostcoder @  5.2.2012,  23:45 Найти цитируемый пост)
в терминах boost.preprocessor - это последовательность. я же, итерируюсь по последовательности, и на каждой итерации раскрываю часть общего выражения.
Это я поняла по кодуsmile Мне любопытно, каким образом буст обманывает препроцессор и итерирует не по аргументам, а по свой скобочной коллекции. Интуиция подсказывает, что внутри это оборачивается в вызов другого макроса, очередной скобочный аргумент передается ему в качестве аргумента... Но как это происходит не пойму smile Исходники буст-препроцессора я не осилила, поэтому и любопытствую, что за трюк такой... Если не сложно.

Цитата(volatile @  6.2.2012,  00:56 Найти цитируемый пост)
а приктике (при статической типизации) это практически бемполезная конструкция, имхо конечно.
А на моей практике это очень нужная конструкция. Мы с тобой просто программируем по-разному, которая экономит много строк кода. Где-то на первой странице я приводила немного надуманый, но наглядный пример.


--------------------
You're face to face
With man who sold the world
PM   Вверх
boostcoder
Дата 6.2.2012, 09:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(newbee @  6.2.2012,  08:44 Найти цитируемый пост)
Макросы можно разворачивать в ({})-форму, это расширение GCC

не знал. попробую.

Цитата(newbee @  6.2.2012,  08:44 Найти цитируемый пост)
Интуиция подсказывает, что внутри это оборачивается в вызов другого макроса, очередной скобочный аргумент передается ему в качестве аргумента.

именно так.

к примеру простой макрос BOOST_PP_SEQ_SIZE(): https://github.com/ryppl/boost-svn/blob/mas...or/seq/size.hpp

макрос:
var = BOOST_PP_SEQ_SIZE((a)(b)©)

развернется в:
var = BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_3

который в свою очередь описан как:
# define BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_3 3

т.е. весь boost.preprocessor работает по нескольким основным принципам. либо по кол-ву аргументов, либо специализациями для всех возможных количеств аргументов.
все на самом деле очень просто.

Добавлено через 3 минуты и 58 секунд
или я не понял вопроса...

Добавлено через 8 минут и 57 секунд
Цитата(newbee @  6.2.2012,  08:44 Найти цитируемый пост)
Макросы можно разворачивать в ({})-форму, это расширение GCC

хм..
http://liveworkspace.org/code/35bcbcc90f05...d71d9b551f41499

дай ссылку на описание расширения.
PM WWW   Вверх
newbee
Дата 6.2.2012, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



Цитата(boostcoder @  6.2.2012,  10:34 Найти цитируемый пост)
дай ссылку на описание расширения. 
У тебя включен pedantic.

http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Компилируй с -std=gnu++98 или -std=gnu++0x


--------------------
You're face to face
With man who sold the world
PM   Вверх
boostcoder
Дата 6.2.2012, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(newbee @  6.2.2012,  09:53 Найти цитируемый пост)
У тебя включен pedantic.

угу.

в общем работает.
попробую доделать..

Добавлено через 2 минуты и 31 секунду
mes, а Вы свой вариант будите доделывать? просто любопытно посмотреть на решение.
я тут еще подумал... для функционального программирования в с++, разработали boost.phoenix. еще попробую с его помощью решить задачу.
PM WWW   Вверх
mes
Дата 6.2.2012, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



boostcoder, мой вариант придет к буст лямбде smile

Цитата(boostcoder @  6.2.2012,  09:04 Найти цитируемый пост)
 разработали boost.phoenix.

еще не приходилось сталкиваться smile



Это сообщение отредактировал(а) mes - 6.2.2012, 10:13


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 6.2.2012, 10:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  6.2.2012,  10:13 Найти цитируемый пост)
мой вариант придет к буст лямбде

 smile 
PM WWW   Вверх
boostcoder
Дата 9.2.2012, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



newbee, итак.
давай посмотрим на препроцессированный вариант твоих тестов:
Код

int main() {
   int b1=0, b2=1, b3=2;

   std::cout << Ext_OR((b1)(Ext_AND((b2)(b1)))(b3)) << std::endl; //wait: 2; recieve: 2
   std::cout << Ext_OR((b1)(Ext_AND((b1)(b2)))(b3)) << std::endl; //wait: 2; recieve: 2
}

результат:
Код

int main() {
   int b1=0, b2=1, b3=2;

   std::cout << ( (b1) ? (b1) : (( !(b2) ? (b2) : ( b1 ) )) ? (( !(b2) ? (b2) : ( b1 ) )) : ( b3 ) ) << std::endl;
   std::cout << ( (b1) ? (b1) : (( !(b1) ? (b1) : ( b2 ) )) ? (( !(b1) ? (b1) : ( b2 ) )) : ( b3 ) ) << std::endl;
}


теперь нужно выявить вложенность "скопов" для того чтоб определить в каком скопе какое выражение должно вычисляться...

Добавлено @ 01:32
лишние скобки уберем..

Добавлено @ 01:36
вот что получилось:
Код

int main() {
   int b1=0, b2=1, b3=2;

   std::cout << (
      (b1)
      ?(b1)
         :!(b2)
            ?(b2)
               :(b1)
            ?!(b2)
               ?(b2)
                  :(b1)
               :(b3)
   ) << std::endl;

   std::cout << (
      (b1)
      ?(b1)
         :!(b1)
            ?(b1)
               :(b2)
            ?!(b1)
               ?(b1)
                  :(b2)
               :(b3)
   ) << std::endl;
}



Это сообщение отредактировал(а) boostcoder - 9.2.2012, 01:37
PM WWW   Вверх
newbee
Дата 9.2.2012, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 4
Всего: 19



boostcoder, у тебя сложно раскрывается AND. Я для наглядности буду возвращать нули вместо самих вычисленных значений.

Код

(and b1 b2 b3) -> b1?(b2?(b3?b3:0):0):0 // так имхо логичнее
(or b1 b2 b3) -> b1?b1:(b2?b2:(b3?b3:0)) //у тебя по-моему так и есть


Теперь... Смотри, внутри OR и AND излишне следовать правилу раскрытия элемента последовательности x?x: Если x - вложенный AND или OR, его можно прямо встроить в выражение. Я не знаю, можно ли это сделать на дефайнах... Это необязательно. Таким образом твой пример принял бы форму
Код

(or b1 (and b1 b2) b3) -> b1?b1:(b1?(b2?b2:0):(b3?b3:0))
/* или
   if?
     then
    :else
 */
b1?
  b1
 :(b1?
     (b2?
        b2
       :0)
    :(b3?
        b3
       :0))


Теперь давай подумаем со скопами...

Код

(and b1 b2 b3) ->  b1?(b2?(b3?b3:0):0):0 -> 

b1?
  (b2?
     (b3?
        b3
       :0)
    :0)
 :0 ->

({typeof(b1) _1=b1;
  _1?
    ({typeof(b2) _2=b2;
      _2?
        ({typeof(b3) _3=b3;
          _3?
            _3
           :0;})
       :0;})
   :0;})


И аналогично должно быть с OR. Потом напишу, если надо. Я нигде не накосячила?


--------------------
You're face to face
With man who sold the world
PM   Вверх
boostcoder
Дата 9.2.2012, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



вроде въехал..

Цитата(newbee @  9.2.2012,  11:03 Найти цитируемый пост)
Я нигде не накосячила?

по моему - нет.
PM WWW   Вверх
math64
Дата 10.2.2012, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Код

#define OR(var,def) ({typeof(var) _tmp = (var); _tmp?_tmp:(def);})
#define TEST(var) OR(var,0)
#define AND(var1,var2) ((var1)?(var2):0)
int main() {
int v1 = 1, v2 = 2, v3 = 3;
// v1 or v2 or v3
cout << OR(v1,OR(v2,TEST(v3))) << endl;
// v1 and v2 and v3
cout << AND(v1,AND(v2,TEST(v3))) << endl;
// v1 and (v2 or v3)
cout << AND(v1,OR(v2,TEST(v3))) << endl;
// v1 or (v2 and v3)
cout << OR(v1,AND(v2,TEST(v3))) << endl;
}

(не проверял)
PM   Вверх
boostcoder
Дата 10.2.2012, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



newbee, смотри какое дело.
код:
Код

int main() {
   int b1=0, b2=1, b3=2;
   std::cout << (
      ({typeof(b1) _1=b1;       // level +1
      _1?
         ({typeof(b2) _2=b2;    // level +2
            _2?
            ({typeof(b3) _3=b3; // level +3
               _3?
                  _3
               :0;
            })                  // level -3
            :0;
         })                     // level -2
         :0;
      })                        // level -1
   ) << std::endl;
}

как ты можешь видеть, тут вложенные скопы. но препроцессор не может рекурсию. он однопроходный.

идеи?
PM WWW   Вверх
boostcoder
Дата 10.2.2012, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



попробовал двумя проходами по последовательности генерировать сначала открывающиеся скопы, потом по той же последовательности, закрывающиеся.

на примере Ext_OR((b1)(b2)(b3)):
Код

({typeof(b1) _0 = b1; (_0) ? (_0) : ({typeof(b2) _1 = b2; (_1) ? (_1) : b3

вроде то, что надо.

но при попытке использовать вложенные макросы "Ext_OR ((b1)(b2)(b3)(Ext_OR ((b1)(b2)(b3))))" получаю ошибку препроцессора.
и правильно. при первом проходе еще ничего не сгенеренно. по этому препроцессор генерит нормально, не смотря на непарные скобки. но при втором проходе, он, "видя" такое ( smile ) синтаксически не правильное "произведение" - спотыкается.

идеи будут?

Добавлено через 2 минуты и 6 секунд
math64, не правильно. в твоем коде все равно выражения будут вычисляться не единожды.
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1191 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.