Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > устраивает ли Вас препроцессор С++?


Автор: Jcs 17.5.2007, 18:57
Здравствуйте, ни у кого не возникало ощущения куцести плюсового препроцессора? У меня, например, периодически возникают случаи, когда его возможностей определенно хватает. Вот один из них. Стандартный случай, когда нужны методы с различными правам доступа ко внутренним переменным. Приходится писать кучу одинакового кода. Данный пример для двух переменных, и то разница уже видна, а что будет когда их число приблизится, например, к 10?
Код

class model
{
    int property0_;
    double propety_1;

public:
    int& property0()
    {return property0_;}

    double& property1()
    {return property1_;}

    const int& property0() const
    {return property0_;}

    const double& property1() const
    {return property2_;}
};

class model
{
    int property0_;
    double propery1_;
public:
    %for_each_member
    %{
        %member_type& %member_name()
        {return %member_name;}

        const %member_type %member_name() const
        {return %member_name;}
    %}
};

Этот случай не первый и не единственный, хотелось бы послушать общество. Заранее спасибо

Автор: MAKCim 17.5.2007, 19:24
в целом хватает
хотя препроцессор GAS (Gnu Assembler) по-лучше будет
я бы добавил
1. Перегрузку макрофункций
Код

#define GET(a) (a)
#define GET(a, b) ((a) + (b))
...

2. Циклы 
Код

int array[SIZE] = {
#repeat SIZE - 1
    __ITERATION__,
#endrep
    SIZE - 1 };

где __ITERATION__ - номер текущей итерации (0, 1, 2, ...)
3. Внутренние макродирективы
Код

#repeat SIZE - 1
    #if __ITERATION__ != 50
        __ITERATION__
    #else
        0
    #endif
#endrep

Автор: JackYF 17.5.2007, 19:33
Совершенству нет предела.
В целом - устраивает, для меня это далеко не самая важная часть программирования.
Добавить функциональность, о которой говорится в начале темы - можно, конечно... вот только, для начала, предложите для нее синтаксис.

Автор: nickless 17.5.2007, 19:34
ИМХО возможностей у препроцессора вполне достаточно, и даже они обычно не используются, потому что в С++ есть много способов сделать то же самое проще/лучше/удобнее. См. например шаблоны.
Насчет твоего примера, можно сделать например так:
Код
#define ACCESSOR(type,name)     type& name() { return name##_; } \
                                const type & name() const { return name##_; }

class model
{
public:
    ACCESSOR( int, property0 )
    ACCESSOR( double, property1 )
private:
    int property0_;
    double property1_;
};


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

Есть еще примеры?

Автор: Daevaorn 17.5.2007, 19:35
Проще пропускать сорсы через какой-нибудь шаблонизатор, чем ждать пока сделают изменения в препроцессоре. Например так как поступает Trolltech.

Автор: JackYF 17.5.2007, 19:36
Цитата(JackYF @  17.5.2007,  19:33 Найти цитируемый пост)
предложите для нее синтаксис. 


Это же надо, 
MAKCim, Максим прочитал мои мысль, пока я ее писал...


Возможно, и неплохо было бы. Правда, для себя не помню случаев, чтобы такие штуки мне понадобились.
Хотя, без сомнения, кому-то понадобится может.

Автор: Daevaorn 17.5.2007, 19:37
Цитата(Jcs @  17.5.2007,  19:57 Найти цитируемый пост)
 Данный пример для двух переменных, и то разница уже видна, а что будет когда их число приблизится, например, к 10?

Кстати, это пример плохого дизайна, а не слобости препроцессора;)

Автор: Hurricane 17.5.2007, 19:44
Daevaorn, ты тоже мыслечитатель?  smile 

Цитата(Daevaorn @  17.5.2007,  11:37 Найти цитируемый пост)
Кстати, это пример плохого дизайна, а не слобости препроцессора;) 


Первая мысль была именно такая.

Добавлено через 4 минуты и 37 секунд
Кстати, а почему нет варианта "В препроцессоре и так много лишнего, сократить до минимума". А то начинаешь юзать всякие темплейтные min/max/swap, а какой-то умник их уже через дефайны переопределил. И начинаешь чесать репу, лихорадочно соображая что сделал не так.

Автор: MAKCim 17.5.2007, 19:50
 smile 
Daevaorn
прикольное число сообщений у тебя 1234  smile 

Автор: maxim1000 17.5.2007, 20:57
ИМХО, основной недостаток препроцессора в том, что он не разбирается в том, что обрабатывает (ну разве что не трогает строки и не обрабатывает max в max1)
в этом смысле шаблоны более "встроены в язык", хотя и возможностей местами поменьше
так что, возможно, было бы неплохо, как-то сближать эти два инструмента...

Автор: nerezus 17.5.2007, 21:19
Собственно шаблоны и есть аналогом препроцессора, просто шаблоны не являются препроцессором по определению )

Автор: jonie 17.5.2007, 23:07
о чем Вы?! вам мало "приятных" и незаметных вещей что дает вам препроцессор?)
Код

#define max(a,b) a<b?b:a         //ну, конечно, сейчас все начнут говорить что мол надо скобок больше) это пример только
....
int a=20;
int b=30;
int c = max(a+=5,b);  //интересно что это даст ....

кстати можете себя проверить.. код даст 50 (а вот на старых компиляторах может дать и не 50)...
смех смехом а я как-то часа 4 искал такую "ошибку" (не в своем коде).... уж никак не пологал что сделан будет макрос... вот чего в голву не пришло, того не пришло)
---------------------
все эти намудреные препроцессорные директивы выливаются в полную мешанину и панику при отладке (нее дай вам столкнуться с ошибкой неявной в большом макросе)...
------------------
Цитата

1. Перегрузку макрофункций
inline - функции чем не устраивают?!
Цитата

2. Циклы 

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

----------------
в общем говоря о "плюсах" не стоит забывать и о минусах....а хочется гуд препроцессор какй вам надо так есть perl ....)) пишите и травите на свои исходники....

Автор: Jcs 18.5.2007, 10:55
nickless
Предложенный вами вариант, конечно, упрощает, но тем не менее нужно для каждого члена класса писать вызов макроса.
Насчет шаблонов полностью согласен, но они не обеспечивают возможность перечисления членов структуры (или я не знаю как это сделать).
Еще один случай, когда это было бы удобно. Например, есть текстовый файл, из которого нужно считать структуру. В случае возможности перечисления можно было бы написать подобный код (данный пример призван показать полезность перечисления, поэтому, пожалуйста, не обращайте внимания на контроль ошибок и проч.):
Код

struct config
{
    int param0,param1;
    float param2,param3;
    double param4,param5;
};

template<ParamType> 
    void read_param(file& ifile,const char* param_name,ParamType& param_ref);

template<StructToRead>
    void read_config(StructToRead& struct_ref,const char* file_name)
{
    file ifile(file_name,IO_read_mode);
    
    %for_each_member_of(StructToRead)
    %{    
        read_param(ifile,"%member_name",struct_ref.%member_name);
    %}
}

Автор: Любитель 18.5.2007, 10:58
Цитата(Hurricane @  17.5.2007,  19:44 Найти цитируемый пост)
Кстати, а почему нет варианта "В препроцессоре и так много лишнего, сократить до минимума". 

Кстати вариант то правильный smile

Если хочется поизвращаться - советую посмотреть ещё на boost::preprocessor. Я толком не смотрел, но если не ошибаюсь циклы там есть. Правда, наверно, с ограниченным количеством итераций (просто не представляю как сделать, юзаю лишь существующие возможности, по-другому).

А вообще шаблоны для кого придумывали? smile

Автор: Jcs 18.5.2007, 11:15
Наверное, вопрос был поставлен не совсем корректно. Правильней было бы спросить - устраивают ли Вас возможности метапрограммирования с С++? Тогда сюда автоматом войдут и шаблоны, и макро. Думаю функциональность шаблонов тоже есть куда расширять. Например в книге "шаблоны. Спавочник пользователя" говорится о возможности включения именованных аргументов шаблонов. Я бы еще добавил частичную специализацию по количеству шаблонных аргументов.

Автор: MAKCim 18.5.2007, 20:24
Цитата(jonie @  17.5.2007,  23:07 Найти цитируемый пост)
inline - функции чем не устраивают?!

ты дашь гарантию, что они будут inline?  smile 
Цитата(jonie @  17.5.2007,  23:07 Найти цитируемый пост)
приведенный пример хоть и встречается, но редко....тем более что если массив такой локальный то ничего хорошего не будет из той инициализации ...

пример надуманный (только, чтобы идентифицировать конструкцию)

Автор: jonie 19.5.2007, 00:36
Цитата

ты дашь гарантию, что они будут inline?   
я не писал компилятор (всмысле писал когда-то как курсовик), но то не о том)=> никаких гарантия я дать не могу, однако хоть стандарт и не оговаривает что inline будут inline, но компилятору я пологаю можно указать чтобы он делал принудилово... опять же как реализовано.
Да и в общем случаем "оно вам надо" ? Обычно большой оптимизации по скорости не будет (время вызова скажем __fastcall функции << времени  цикла (или иной, не подходящей под определение inline, как посчитает (если посчитает) умный компилятор) , т.о. этим временем можно пренебречь. Безусловно, существуют задачи, в которых размер стека жестко ограничен (кодинг железа, я пологаю),но с таким вещаями я не знаком и думаю там есть средства....
Цитата

Добавлено через 4 минуты и 37 секунд
Кстати, а почему нет варианта "В препроцессоре и так много лишнего, сократить до минимума". А то начинаешь юзать всякие темплейтные min/max/swap, а какой-то умник их уже через дефайны переопределил. И начинаешь чесать репу, лихорадочно соображая что сделал не так.
упс, когда писал свой пост пропустил это, но, как минимум я не один так считаю) и то гуд... это - мой вариант выбора.

Автор: MAKCim 19.5.2007, 08:13
Цитата(jonie @  19.5.2007,  00:36 Найти цитируемый пост)
но компилятору я пологаю можно указать чтобы он делал принудилово... опять же как реализовано.

вот именно, переносимость будет -> 0
Цитата(jonie @  19.5.2007,  00:36 Найти цитируемый пост)
Да и в общем случаем "оно вам надо" ? Обычно большой оптимизации по скорости не будет (время вызова скажем __fastcall функции << времени  цикла (или иной, не подходящей под определение inline, как посчитает (если посчитает) умный компилятор) , т.о. этим временем можно пренебречь.

макросы нужны не только для эмуляции inline

Автор: JackYF 19.5.2007, 12:12
ИМХО, есть несколько принципиальных случаев/моментов, когда макросы незаменимы в принципе. То есть аналогию с помощью чисто языковых конструкций построить не удастся.
Есть еще группа случаев, когда удастся, но слишком дорогой ценой (размер или производительность пострадают).
В остальных случаях можно использовать [шаблонные ][inline ]функции.

Автор: vinter 19.5.2007, 13:02
а смысл данного опроса?  допустим мне не нравится то то, то то. Кто то согласится, кто то нет. Но это не изменит ничего. Какой-то бесполезный топик. извиняюсь за оффтоп

Автор: Любитель 19.5.2007, 14:02
Цитата(Jcs @  18.5.2007,  11:15 Найти цитируемый пост)
Правильней было бы спросить - устраивают ли Вас возможности метапрограммирования с С++?

Вот, если так - поддержу. Только не макросы.

MAKCim, вот в реальной жизни все твои примеры с циклами и перегрузкой для макросов когда-нибудь хотелось использовать (я, конечно, про плюсы)? Сомневаюсь, если честно.

Цитата(MAKCim @  19.5.2007,  08:13 Найти цитируемый пост)
макросы нужны не только для эмуляции inline 

Не спорю.

Цитата(MAKCim @  18.5.2007,  20:24 Найти цитируемый пост)
пример надуманный 

Вот именно. Можешь представить практические примеры (точнее - похожие на практические), где такое можно было бы красиво использовать?

Единственное, что кстати не помешает в препроцессоре - области видимости макросов (банальные блоки). Но это вроде и так обещали...

Цитата(vinter @  19.5.2007,  13:02 Найти цитируемый пост)
а смысл данного опроса?  допустим мне не нравится то то, то то. Кто то согласится, кто то нет. Но это не изменит ничего. Какой-то бесполезный топик. извиняюсь за оффтоп 

Ну, я бы не сказал, что бесполезный. Может ничего и не изменит (99,99999 %), но поговорить интересно smile

Автор: MAKCim 19.5.2007, 15:47
Цитата(Любитель @  19.5.2007,  14:02 Найти цитируемый пост)
MAKCim, вот в реальной жизни все твои примеры с циклами и перегрузкой для макросов когда-нибудь хотелось использовать (я, конечно, про плюсы)? Сомневаюсь, если честно.

хотелось пару раз
Цитата(Любитель @  19.5.2007,  14:02 Найти цитируемый пост)
Можешь представить практические примеры (точнее - похожие на практические), где такое можно было бы красиво использовать?

Код

#define SYMBOL(name, value)    \
    __asm__(#name" = %0" : : "I" (value))

static void __generate() {
#repeat COUNT
    #ifdef value#__ITERATION__
        SYMBOL(value#__ITERATION__, value#__ITERATION__);
    #endif
#endrep
}

хотя пример тоже какой-то нереальный получился  smile 

Автор: Любитель 19.5.2007, 16:16
Цитата(MAKCim @  19.5.2007,  15:47 Найти цитируемый пост)
хотя пример тоже какой-то нереальный получился  

 smile По-моему, совсем нереальный. Препроцессор для асма - это совсем другой вопрос, ибо там шаблонов нет smile Ввиду полнейшей непортируемости вышенаписанного кода - тяжело говорить про расширение стандартного препроцессор для этого...

Автор: MAKCim 19.5.2007, 16:42
Любитель
в С тоже нет шаблонов  smile 
а так подумаю на досуге над примером... реальным  smile 
кстати, если ты с make знаком, мне там очень нравятся функции типа
$(foreach)
...
можно было бы писать такое
Код

#list DIRS a, b, c, d, e, f, g
#foreach DIRS
        #include #__CURRENT__
#endeach

 smile 

Автор: nerezus 19.5.2007, 17:29
Цитата

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

Автор: Mayk 19.5.2007, 17:31
Цитата(Любитель @  19.5.2007,  18:02 Найти цитируемый пост)

MAKCim, вот в реальной жизни все твои примеры с циклами и перегрузкой для макросов когда-нибудь хотелось использовать (я, конечно, про плюсы)? Сомневаюсь, если честно.

В G++  схожая техника используется для  эмуляции Variadic Templates(google).  

Цитата(/usr/include/c++/4.0/tr1/tuple)

.....
#define _SHORT_REPEAT
#define _GLIBCXX_REPEAT_HEADER <tr1/tuple_iterate.h>
#include <tr1/repeat.h>
#undef _GLIBCXX_REPEAT_HEADER
#undef _SHORT_REPEAT


А вот самое интересное:
Цитата(/usr/include/c++/4.0/tr1/tuple_iterate.h)

.....
/// @brief class tuple_size
template<_GLIBCXX_TEMPLATE_PARAMS>
  struct tuple_size<tuple<_GLIBCXX_TEMPLATE_ARGS> >
  { static const int value = _GLIBCXX_NUM_ARGS; };


По топику --- для генерации сложных хедеров использую питон.

Автор: bsa 19.5.2007, 18:53
Цитата(MAKCim @ 19.5.2007,  16:42)
Любитель
в С тоже нет шаблонов  smile 
а так подумаю на досуге над примером... реальным  smile 
кстати, если ты с make знаком, мне там очень нравятся функции типа
$(foreach)
...
можно было бы писать такое
Код

#list DIRS a, b, c, d, e, f, g
#foreach DIRS
        #include #__CURRENT__
#endeach

 smile

Ужас! Я на 100% уверен, найдется "профессионал", который сделает определение DIR в одном месте, а подобное использование в другом. Вот обрадуются же те, кто отлаживать возьмется (модифицировать)... smile 

Автор: JackYF 20.5.2007, 01:51
Цитата(Jcs @  18.5.2007,  10:55 Найти цитируемый пост)
но они не обеспечивают возможность перечисления членов структуры


Кстати, вот одна из нескольких дельных мыслей. Мне несколько раз этой возможности не хватало. Как замутить такое - не нашел, и сам не придумал. Можно ли?
Компилятор ведь умеет, когда составляет конструктор копирования по-умолчанию.

Автор: Hurricane 20.5.2007, 02:09
Цитата(JackYF @  19.5.2007,  17:51 Найти цитируемый пост)
Кстати, вот одна из нескольких дельных мыслей. Мне несколько раз этой возможности не хватало. Как замутить такое - не нашел, и сам не придумал. Можно ли?
Компилятор ведь умеет, когда составляет конструктор копирования по-умолчанию.


Что будем перечислять для public, protected, private мемберов наследуемого класса в С++? Я бы понял, если бы это делал компилятор (конструкция языка), но препроцессор... Или препроцессор должен знать правила доступа для разных типов наследования? Или для С должен быть другой препроцессор?

Насчет foreach. В С/С++ нет контейнеров как интегральных типов данных _языка_. Они реализованы на уровне библиотек (boost, stl  и т.д.), и библиотеки поддерживают foreach (или for_each). Я не понимаю, почему это должно поддерживаться на уровне компилятора (для языка) или препроцессора. Вариант с {...in list} - это тоже частный случай контейнера, он должен каким-то образом создаться. Для каких типов данных? Это должен решать программист или препроцессор?

Сравните с Perl, где тип контейнеров - часть языка.

Автор: MAKCim 20.5.2007, 10:05
Hurricane
про что ты говоришь, и что я написал  smile 

Автор: JackYF 20.5.2007, 18:12
Цитата(Hurricane @  20.5.2007,  02:09 Найти цитируемый пост)
Я бы понял, если бы это делал компилятор (конструкция языка)


Да кто спорит? Компилятор, он, родимый. Главное - функциональная возможность, а не чем и через что она будет реализована.
Пускай будет конструкция языка. Просто по сути это будет "языковой препроцессор".

Цитата(Hurricane @  20.5.2007,  02:09 Найти цитируемый пост)
Насчет foreach.

А насчет for_each про контейнеры речь и не шла. См. пост MAKCimа выше.

Автор: Hurricane 20.5.2007, 19:22
Цитата(MAKCim @  20.5.2007,  02:05 Найти цитируемый пост)
Hurricane, 
про что ты говоришь, и что я написал 

Ты гарантируешь, что не найдется умник, который будет использовать это не для включения файлов, а для работы с  данными или чего-нибудь еще? Не верю.

Автор: Jcs 21.5.2007, 15:45
Hurricane
Для перечисления методов с различным доступом можно использовать ключевые слова (for each protected, public ..) - здесь проблем не вижу. Другой вопрос - на кого можно было бы возложить данную задачу (препроцессор или шаблоны) и стоит ли ее вообще решать. Судя по обсуждению - большинство довольствуется существующими возможностями метапрограммирования, а значит никаких нововведений в данном ключе не предвидится. Может быть это правильно, и позволит избежать появления винегрета типа c#, но, с другой стороны, если расширить функциональность (без потери в производительности, совместимости и удобстве) то наверняка появится и спрос на подобные возможности.

Автор: Hurricane 21.5.2007, 18:40
Цитата(Jcs @ 21.5.2007,  07:45)
Hurricane
Для перечисления методов с различным доступом можно использовать ключевые слова (for each protected, public ..) - здесь проблем не вижу. Другой вопрос - на кого можно было бы возложить данную задачу (препроцессор или шаблоны) и стоит ли ее вообще решать. Судя по обсуждению - большинство довольствуется существующими возможностями метапрограммирования, а значит никаких нововведений в данном ключе не предвидится. Может быть это правильно, и позволит избежать появления винегрета типа c#, но, с другой стороны, если расширить функциональность (без потери в производительности, совместимости и удобстве) то наверняка появится и спрос на подобные возможности.

Ключевые слова pivate, protected и т.д. не спасут - препроцессор все равно должен будет иметь представление о видимостях членов и методов классов - они объявляются все скопом в соответствующих секциях, а не каждый индивидуйно (как в С#, например). Кроме того, если класс наследуется и какой-либо из членов или методов не перегружен (используется из родительского класса) - надо ли их включать? Можно, конечно, нагородить ключевых слов для всех возможных ситуаций, но я не думаю, что это будет хорошо.

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

Ну консерватор я, консерватор!  smile 

Автор: HappyLife 21.5.2007, 18:52
Народ любит поспорить в том что всё имеет место жить, и что умные люди которые "не советуют" вовсе не умные раз "не советуют".

Автор: MAKCim 21.5.2007, 19:43
Цитата(Hurricane @  20.5.2007,  19:22 Найти цитируемый пост)
Ты гарантируешь, что не найдется умник, который будет использовать это не для включения файлов, а для работы с  данными или чего-нибудь еще? Не верю.

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

Автор: Hurricane 21.5.2007, 19:50
Цитата(MAKCim @  21.5.2007,  11:43 Найти цитируемый пост)
более того, следуя твоей логике, вообще следует много от чего отказаться, потому как "найдется умник..."  


Погоди, я попробую угадать... Т.е. на самом деле - умники не находятся, сложность конструкций никак не связана с их безопасностью, и вообще, это все выдумки Hurrican'а, так?  smile 

Автор: MAKCim 21.5.2007, 19:52
Цитата(Hurricane @  21.5.2007,  19:50 Найти цитируемый пост)
Погоди, я попробую угадать... Т.е. на самом деле - умники не находятся, сложность конструкций никак не связана с их безопасностью, и вообще, это все выдумки Hurrican'а, так?

шаблоны С++ сложны? 
безопасны?

Автор: Hurricane 21.5.2007, 20:03
Цитата(MAKCim @  21.5.2007,  11:52 Найти цитируемый пост)
шаблоны С++ сложны? 
безопасны? 

1. Мы говорим о шаблонах вообще (как о конструкции языка) или о конкретных реализациях в виде boost, stl и т.п.?
2. Возможно, что это только мне так невезло, но я видел намного больше проблем, созданных препроцессором (неумелым его использованием), чем шаблонами. Во всяком случае шаблоны - часть языка, и в большинстве случаев компилятор тут же дает по рукам при попытке неправильного их использования. С препроцессором это не так.


Автор: Любитель 25.5.2007, 10:02
Цитата(MAKCim @  19.5.2007,  16:42 Найти цитируемый пост)
в С тоже нет шаблонов  

В названии темы стоят плюсы  smile 

Цитата(nerezus @  19.5.2007,  17:29 Найти цитируемый пост)
 А мне кажестся, что на уровне синтаксиса это было бы удобнее

Угу.

Цитата(Mayk @  19.5.2007,  17:31 Найти цитируемый пост)
А вот самое интересное:

Опять-таки - гораздо лучше иметь синтаксис языковой для переменного кол-ва типов шаблонов. Если не ошибаюсь сие уже давно обсуждается комитетом.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)