Как быть, если аргументы BOOST_PP_IF - макросы?
От: enji  
Дата: 25.08.10 05:32
Оценка:
Хочется сгенерить такое:

void f();
template<class A1> void f(A1 a1);
template<class A1, class A2> void f(A1 a1, A2 a2);
...


Пытаюсь так:

#define PRINT(Z, N, DATA) \
  BOOST_PP_IF(N, template <BOOST_PP_ENUM_PARAMS_Z(Z, N, class A)>, BOOST_PP_EMPTY()) \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));
  
BOOST_PP_REPEAT(5, PRINT, ~)


но не работает. Если убрать IF и void f() без параметров прописать руками, то все нормально:

void f();
#define PRINT(Z, N, DATA) \
  template <BOOST_PP_ENUM_PARAMS_Z(Z, N, class A)> \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));
  
BOOST_PP_REPEAT(5, PRINT, ~)


Можно ли как-то извернуться с IF?
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
Re: Как быть, если аргументы BOOST_PP_IF - макросы?
От: nen777w  
Дата: 25.08.10 06:57
Оценка:
Может быть попробовать сделать через:

BOOST_PP_SEQ_FILTER + BOOST_PP_GREATER

Сейчас к сожалению времени нет, но если к обеду не получиться у Вас — подключусь помогу. На самом деле там ничего сложного.
Главное всегда помнить что препроцессор однопроходный.
Re[2]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: enji  
Дата: 25.08.10 08:43
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Может быть попробовать сделать через:


N>BOOST_PP_SEQ_FILTER + BOOST_PP_GREATER


N>Сейчас к сожалению времени нет, но если к обеду не получиться у Вас — подключусь помогу. На самом деле там ничего сложного.

N>Главное всегда помнить что препроцессор однопроходный.

Так не работает...

#define PRED(s, data, elem) BOOST_PP_GREATER(data, 0)

#define PRINT(Z, N, DATA) \
  BOOST_PP_SEQ_FILTER(PRED, N, (template <BOOST_PP_ENUM_PARAMS_Z(Z, N, class A)>) ) \
  void f()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const;

BOOST_PP_REPEAT(5, PRINT, ~)


Да и BOOST_PP_SEQ_FILTER вернет последовательность, т.е. (template ...), а как скобки убрать? SEQ_ELEM?
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
Re: Как быть, если аргументы BOOST_PP_IF - макросы?
От: Vain Россия google.ru
Дата: 25.08.10 10:37
Оценка: 2 (1)
Здравствуйте, enji, Вы писали:

E>Хочется сгенерить такое:

E>...
E>Можно ли как-то извернуться с IF?
Я когда-то расширитель написал, можно посмотреть здесь
Автор: Vain
Дата: 22.12.07
.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: nen777w  
Дата: 26.08.10 13:41
Оценка: 5 (1) :))) :)
Держите, получилось!:

#define     _SEMICOLON() ;

#define     DECLARE_FN( fn ) \
    BOOST_PP_SEQ_ELEM(0, fn) BOOST_PP_SEQ_ELEM(1, fn)

#define     DECL_TUPLE( cnt, prefT ) \
    BOOST_PP_COMMA_IF( BOOST_PP_NOT_EQUAL(cnt,1) ) BOOST_PP_CAT(prefT,cnt)

#define     DECLARE_TPL_FN_TUPLE__FOR_PRED( r, state ) \
    BOOST_PP_NOT_EQUAL( \
        BOOST_PP_TUPLE_ELEM(2, 0, state), \
        BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(2, 1, state)) \
    )

#define     DECLARE_TPL_FN_TUPLE__FOR_OP( r, state ) \
    ( \
        BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(2, 0, state)), \
        BOOST_PP_TUPLE_ELEM(2, 1, state) \
    )

#define DECLARE_TPL_FN_TUPLE__MACRO(r, state) \
    DECL_TUPLE( BOOST_PP_TUPLE_ELEM(2, 0, state), A )
    

#define     DECLARE_TPL_FN_TUPLE( count ) \
    ( BOOST_PP_FOR( (1,count), DECLARE_TPL_FN_TUPLE__FOR_PRED, DECLARE_TPL_FN_TUPLE__FOR_OP, DECLARE_TPL_FN_TUPLE__MACRO ) )


#define     DECL_TEMPLATE_PARAMS( count ) \
    BOOST_PP_TUPLE_TO_SEQ( count, DECLARE_TPL_FN_TUPLE( count ) )

#define     TRANSFORM( s, data, elem ) \
    typename elem

#define     TRANSFORM_typename(seq) \
    BOOST_PP_SEQ_TRANSFORM( TRANSFORM, 0, seq )

#define     PRODUCE_TPL_FN( count ) \
    template< BOOST_PP_SEQ_ENUM( TRANSFORM_typename( DECL_TEMPLATE_PARAMS( count ) ) ) >

#define     PRODUCT( count, fn ) \
    PRODUCE_TPL_FN( count ) DECLARE_FN( fn )( BOOST_PP_ENUM_BINARY_PARAMS( count, A, a) ) _SEMICOLON()

#define     PRODUCE_TPL_FN__FOR_PRED( r, state ) \
    BOOST_PP_NOT_EQUAL( BOOST_PP_TUPLE_ELEM(3, 0, state), BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(3, 1, state) ) )

#define     PRODUCE_TPL_FN__FOR_OP( r, state ) \
    ( BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(3, 0, state)), BOOST_PP_TUPLE_ELEM(3, 1, state), BOOST_PP_TUPLE_ELEM(3, 2, state) )

#define     PRODUCE_TPL_FN__FOR_MACRO( r, state ) \
    PRODUCT( BOOST_PP_TUPLE_ELEM(3, 0, state), BOOST_PP_TUPLE_ELEM(3, 2, state) )

#define     GEN_TPL_FN( fn_name, count ) \
    DECLARE_FN( fn_name )() _SEMICOLON() \
    BOOST_PP_FOR( (1,count, fn_name), PRODUCE_TPL_FN__FOR_PRED, PRODUCE_TPL_FN__FOR_OP, PRODUCE_TPL_FN__FOR_MACRO )
    
    
GEN_TPL_FN( (void)(foo), 3 )


// без шаблонов порождает:
GEN_TPL_FN( (void)(foo), 0 )
void  foo () ;





// с шаблонами порождает:
GEN_TPL_FN( (void)(foo), 5 )
void  foo () ; 
template< typename A1 > void  foo (  A0 a0 ) ; 
template< typename A1, typename A2 > void  foo (  A0 a0 , A1 a1 ) ; 
template< typename A1, typename A2, typename A3 > void  foo (  A0 a0 , A1 a1 , A2 a2 ) ; 
template< typename A1, typename A2, typename A3, typename A4 > void  foo (  A0 a0 , A1 a1 , A2 a2 , A3 a3 ) ; 
template< typename A1, typename A2, typename A3, typename A4, typename A5 > void  foo (  A0 a0 , A1 a1 , A2 a2 , A3 a3 , A4 a4 ) ;


Что можно сделать лучше, ну например расширить сиквенс (void)(foo) до (void)(foo)(A)(a)
что бы можно было задавать имена параметров шаблона и аргументов функций.
Ну или много чего другого

з.ы.
boost — кульная либа.
Re[4]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: nen777w  
Дата: 26.08.10 14:09
Оценка:
Небольшое исправление:

#define     DECL_TUPLE( cnt, prefT ) \
    BOOST_PP_COMMA_IF( BOOST_PP_NOT_EQUAL(cnt,1) ) BOOST_PP_CAT(prefT,BOOST_PP_DEC(cnt))
Re[5]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: Vain Россия google.ru
Дата: 26.08.10 15:55
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Небольшое исправление:

N>
N>#define     DECL_TUPLE( cnt, prefT ) \
N>    BOOST_PP_COMMA_IF( BOOST_PP_NOT_EQUAL(cnt,1) ) BOOST_PP_CAT(prefT,BOOST_PP_DEC(cnt))
N>

С моим расширением — короче:
//#define LINE_TERMINATOR

#define FOO_TMPL_1(n) void foo();LINE_TERMINATOR
#define FOO_TMPL_2(n) template< BOOST_PP_ENUM_PARAMS(n,class T) > void foo(BOOST_PP_ENUM_BINARY_PARAMS(n,T,p));LINE_TERMINATOR

#define GENERATOR_FN_FOO(z,n,data)\
    BOOST_PP_MACRO_IF(n,\
      (n),\
      (n),\
      FOO_TMPL_2,\
      FOO_TMPL_1)

BOOST_PP_REPEAT(5,GENERATOR_FN_FOO,*)

void foo();
template<  class T0 > void foo( T0 p0);
template<  class T0 , class T1 > void foo( T0 p0 , T1 p1);
template<  class T0 , class T1 , class T2 > void foo( T0 p0 , T1 p1 , T2 p2);
template<  class T0 , class T1 , class T2 , class T3 > void foo( T0 p0 , T1 p1 , T2 p2 , T3 p3);

[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[6]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: nen777w  
Дата: 27.08.10 10:11
Оценка:
V>С моим расширением — короче:
V>

Гм... да на много. Может вам того... это предложить в boost ?
Re[7]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: Vain Россия google.ru
Дата: 27.08.10 11:58
Оценка:
Здравствуйте, nen777w, Вы писали:

V>>С моим расширением — короче:

V>>
N>Гм... да на много. Может вам того... это предложить в boost ?
Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[8]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: _nn_ www.nemerleweb.com
Дата: 19.06.11 15:59
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, nen777w, Вы писали:


V>>>С моим расширением — короче:

V>>>
N>>Гм... да на много. Может вам того... это предложить в boost ?
V>Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.

Вы хотя бы добавьте в Trac.
А там будет время приложите патч.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[9]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: Vain Россия google.ru
Дата: 19.06.11 16:13
Оценка:
Здравствуйте, _nn_, Вы писали:

V>>>>С моим расширением — короче:

V>>>>
N>>>Гм... да на много. Может вам того... это предложить в boost ?
V>>Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.
__>Вы хотя бы добавьте в Trac.
__>А там будет время приложите патч.
А надо ли? Я к тому что этот аддон мало кому реально нужен, а если нужен, то можно найти на RSDN'е
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[10]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: _nn_ www.nemerleweb.com
Дата: 19.06.11 16:18
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, _nn_, Вы писали:


V>>>>>С моим расширением — короче:

V>>>>>
N>>>>Гм... да на много. Может вам того... это предложить в boost ?
V>>>Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.
__>>Вы хотя бы добавьте в Trac.
__>>А там будет время приложите патч.
V>А надо ли? Я к тому что этот аддон мало кому реально нужен, а если нужен, то можно найти на RSDN'е

Если кому-то будет очень нужен, так еще и в буст добавят
Пусть тикет висит, когда-нибудь может пригодится.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: Vain Россия google.ru
Дата: 19.06.11 17:29
Оценка:
Здравствуйте, _nn_, Вы писали:

V>>>>>>С моим расширением — короче:

V>>>>>>
N>>>>>Гм... да на много. Может вам того... это предложить в boost ?
V>>>>Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.
__>>>Вы хотя бы добавьте в Trac.
__>>>А там будет время приложите патч.
V>>А надо ли? Я к тому что этот аддон мало кому реально нужен, а если нужен, то можно найти на RSDN'е
__>Если кому-то будет очень нужен, так еще и в буст добавят
__>Пусть тикет висит, когда-нибудь может пригодится.
Тут есть несколько но:
  1. Есть версия в которой много чего ещё добавлено, но пока-что недотестировано.
  2. Некоторые исходники генерятся по шаблону, т.е. есть для этого скрипт в виде bat-файл+exe-файл, непонятно пока как это переправить в буст. Хотелось бы выложить не только сгенерённые исходники, но и скрипты их генерирующие, непонятно что со скриптами делать, под какой шелл переписывать?
  3. Есть тесты для некоторой добавленной функциональности, куда их пихать и в каком виде?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[10]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: nen777w  
Дата: 19.06.11 20:20
Оценка:
V>А надо ли? Я к тому что этот аддон мало кому реально нужен, а если нужен, то можно найти на RSDN'е
Кстати Я вот тут
Автор: nen777w
Дата: 16.06.11
предложил делиться приёмами на boost::preprocessor
preprocessor
Re[12]: Как быть, если аргументы BOOST_PP_IF - макросы?
От: _nn_ www.nemerleweb.com
Дата: 20.06.11 06:27
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, _nn_, Вы писали:


V>>>>>>>С моим расширением — короче:

V>>>>>>>
N>>>>>>Гм... да на много. Может вам того... это предложить в boost ?
V>>>>>Там перед тем как предлогать надо тестировать под кучей компиляторов, а это надо как минимум всех их ставить и настраивать boost.build. Вообщем на всё это нужно много времени, которого пока что не хватает.
__>>>>Вы хотя бы добавьте в Trac.
__>>>>А там будет время приложите патч.
V>>>А надо ли? Я к тому что этот аддон мало кому реально нужен, а если нужен, то можно найти на RSDN'е
__>>Если кому-то будет очень нужен, так еще и в буст добавят
__>>Пусть тикет висит, когда-нибудь может пригодится.
V>Тут есть несколько но:
  1. V>Есть версия в которой много чего ещё добавлено, но пока-что недотестировано.
    Тогда сюда , мы потестируем
  2. V>Некоторые исходники генерятся по шаблону, т.е. есть для этого скрипт в виде bat-файл+exe-файл, непонятно пока как это переправить в буст. Хотелось бы выложить не только сгенерённые исходники, но и скрипты их генерирующие, непонятно что со скриптами делать, под какой шелл переписывать?

    Для Boost.MPL используется скрипт Питона:
    http://svn.boost.org/svn/boost/trunk/libs/mpl/preprocessed/
    Можно сделать по образу и подобию.

  3. V>Есть тесты для некоторой добавленной функциональности, куда их пихать и в каком виде?
    Тесты в виде Boost.Test .

А можно заранее оформить структуру папок в стиле boost-а.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: BOOST_PP_IF - решения
От: jazzer Россия Skype: enerjazzer
Дата: 22.06.11 01:39
Оценка:
Здравствуйте, enji, Вы писали:

E>
E>#define PRINT(Z, N, DATA) \
E>  BOOST_PP_IF(N, template <BOOST_PP_ENUM_PARAMS_Z(Z, N, class A)>, BOOST_PP_EMPTY()) \
E>  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));


E>но не работает. Если убрать IF и void f() без параметров прописать руками, то все нормально:

Я бы так и сделал, оно проще

E>Можно ли как-то извернуться с IF?

Можно:
#define PRINT(Z, N, DATA) \
  BOOST_PP_EXPAND(BOOST_PP_IF(N, BOOST_PP_TUPLE_REM(N), BOOST_PP_EMPTY)\
                  BOOST_PP_IF(N, (template <BOOST_PP_ENUM_PARAMS_Z (Z, N, class A) >), ())) \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));

Идея в том, чтобы экранировать получающиеся в результате раскрытия BOOST_PP_ENUM_PARAMS запятые.
В данном случае я их упаковываю в TUPLE (добавляя скобки вокруг), который потом очищаю от скобок применением BOOST_PP_TUPLE_REM.

Вариант с одним BOOST_PP_IF и дополнительной макрой, генерящей template<...>:
#define TPL(Z,N,text) template<BOOST_PP_ENUM_PARAMS_Z (Z, N, text)>

#define PRINT(Z, N, DATA) \
  BOOST_PP_IF(N, TPL, BOOST_PP_TUPLE_EAT(3))(Z,N,class A) \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));

Достоинство этого метода в его скорости — раскрываться будет только то, что нужно, а не все сразу и потом делаться выбор из всего раскрытого.
В данном случае большой рояли не играет, но в случае условного раскрытия более тяжелых макросов это — самый правильный путь.

Вариант с вариадиками:
#define TPL(...) template< __VA_ARGS__ >
#define TUPLE_EAT(...)

#define PRINT(Z, N, DATA) \
  BOOST_PP_IF( N, TPL, TUPLE_EAT )( BOOST_PP_ENUM_PARAMS_Z(Z, N, class A) ) \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));


Еще вариант с ними же, более обобщенный и ближе к оригинальному примеру (используется вариадик TUPLE_REM вместо BOOST_PP_TUPLE_REM(N) — естественное и удобное расширение, так же как и TUPLE_EAT вместо BOOST_PP_TUPLE_EAT(N)):
#define TUPLE_REM(...) __VA_ARGS__

#define PRINT(Z, N, DATA) \
  BOOST_PP_IF( N, TUPLE_REM, BOOST_PP_TUPLE_EAT(1) )      \
    (template < BOOST_PP_ENUM_PARAMS_Z (Z, N, class A) >) \
  void f(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, a));


BOOST_PP_TUPLE_EAT(1) можно заменить на вариадик TUPLE_EAT из предыдущего примера (и наоборот, в этом конкретном случае).

В обоих подходах используется подход функционального программирования — BOOST_PP_IF возвращает функцию, которая потом применяется к списку аргументов, вместо того, чтоб работать сразу с примененными аргументами.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.