Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.03;
Скачать: CL | DM;

Вниз

Задача знатокам С++   Найти похожие ветки 

 
Igorek ©   (2004-09-09 17:23) [0]

Написать ф-цию
void f1(int x...) { f2(???); },
которая вызывала бы
void f2(int x...) {}
и передавала все свои аргументы ей.


 
вразлет ©   (2004-09-09 17:25) [1]

и в чем проблема?


 
wicked ©   (2004-09-09 18:01) [2]

хы-хы... говорим f1, подразумеваем f2?...
#define f1 f2
:)


 
Igorek ©   (2004-09-09 19:11) [3]


> вразлет ©   (09.09.04 17:25) [1]
> и в чем проблема?

У кого?

> wicked ©   (09.09.04 18:01) [2]
> хы-хы... говорим f1, подразумеваем f2?...
> #define f1 f2

Условие читаем? :-)


 
wicked ©   (2004-09-09 19:33) [4]

> Igorek [3]
задача решена?... нигде же не сказано, что можно использовать, а что - нет... :)

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


 
wl   (2004-09-09 20:10) [5]


f2(int x) { return x;}
f1(int x) { f2(x); return 0;}

пойдёт такое решение?


 
wl   (2004-09-09 20:11) [6]

ааа, возвращают void... значит без return-ов...


 
Igorek ©   (2004-09-09 20:45) [7]


> wicked ©   (09.09.04 19:33) [4]
> > Igorek [3]
> задача решена?... нигде же не сказано, что можно использовать,
> а что - нет... :)

Сказано
> Написать ф-цию
> void f1(int x...) { f2(???); },

А что будет, если поставишь #define f1 f2 ? Зацикливание рекурсией или "ф-ция уже определена".


> а если "по правильному", то задачу без какого-либо препроцессора
> или егенратора не решить...

Вот меня это тоже интересует.

> wl   (09.09.04 20:10) [5]
> f2(int x) { return x;}
> f1(int x) { f2(x); return 0;}
> пойдёт такое решение?

Неа. При вызове f1(1,2) - второй параметр не передастся в f2.


 
VMcL ©   (2004-09-09 21:37) [8]

>>Igorek ©  (09.09.04 17:23)

Написать ф-цию
void f1(int x...) { f2(???); },
которая вызывала бы
void f2(int x...) {}
и передавала все свои аргументы ей.


void f2(...)
{
}

#define f1 f2


 
Verg ©   (2004-09-09 21:45) [9]

Бред какой-то.
Ты чего, на va_list (va_start, va_arg...) тянешь?
Что блин за задачки с тремя неизвестными, половина из которых у тебя в уме соталась?


 
wicked ©   (2004-09-09 22:03) [10]

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


 
Verg ©   (2004-09-09 22:41) [11]


> не тянет, поскольку не сказано, что есть один фиксированный
> параметр...



> Написать ф-цию
> void f1(int x...) { f2(???); },
> которая вызывала бы
> void f2(int x...) {}
> и передавала все свои аргументы ей.


? :))


 
вразлет ©   (2004-09-10 09:17) [12]

Афтар, а что такое "знатоки С++" ?


 
Igorek ©   (2004-09-10 10:36) [13]


> VMcL ©   (09.09.04 21:37) [8]
> void f2(...)
> {
> }
> #define f1 f2

Прошу прощения, а где собственно f1?
Люди, я не прошу просто сделать возможным вызов в виде f1(...). Мне нужно реальное тело функции, которая вызывается.

> Verg ©   (09.09.04 21:45) [9]
> Бред какой-то.
> Ты чего, на va_list (va_start, va_arg...) тянешь?
> Что блин за задачки с тремя неизвестными, половина из которых
> у тебя в уме соталась?

Фиксированый параметр для va_start есть. Необязательные параметры и их колл. вам и знать не надо - это знает только создатель f2.
Все что надо - известно.

> wicked ©   (09.09.04 22:03) [10]
> не тянет, поскольку не сказано, что есть один фиксированный
> параметр

Ну как не сказано? А f1(int x...) - это что такое?


 
VMcL ©   (2004-09-10 13:09) [14]

>>Igorek ©  (10.09.04 10:36) [13]

>Люди, я не прошу просто сделать возможным вызов в виде f1(...). Мне нужно реальное тело функции, которая вызывается.

Можно и гланды через задний проход удалять. Но вот только зачем?


 
GuAV ©   (2004-09-10 21:07) [15]

Igorek ©   (10.09.04 10:36) [13]
Вот,

> через задний проход


procedure F1(X, Y, Z: Integer);
begin
 ShowMessageFmt("X=%D Y=%D Z=%D",[X,Y,Z]);
end;

procedure FF2;  // Параметров не знаем
asm
 //  Реальное тело F2
 PUSH OFFSET F1
end;

type
 TF1 = procedure(X, Y, Z: Integer);

var
 PF2: pointer = @FF2;
 F2: TF1 absolute PF2;


 
Verg ©   (2004-09-10 21:33) [16]


> Фиксированый параметр для va_start есть. Необязательные
> параметры и их колл. вам и знать не надо - это знает только
> создатель f2.
> Все что надо - известно.


Так ты о чем же собственно?
Умных слов-загадок потолкать или что? :))


 
DiamondShark ©   (2004-09-11 11:01) [17]

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

Поэтому решение может быть примерно такое: погадать по звёздам о длине переданных параметров, ассемблерной вставкой переписать их в стек и вызвать функцию.


 
Артем Запаранюк ©   (2004-09-11 17:56) [18]

Мой вариант.

int array[]={10,8,6,4,2,0};

void f2(int x, int [])
{
//тело функции, где выполняются операции над переменными
}

void f1(int x, int ara[])
{
f2 (x, ara);
}

//Вызываем функцию ф1
f1(5,array);

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

Такой подход реализован, например, в функции WinMain (см. help по С++).


 
Igorek ©   (2004-09-12 15:19) [19]


> VMcL ©   (10.09.04 13:09) [14]
> Можно и гланды через задний проход удалять. Но вот только
> зачем?

Неудачное сравнение. Здесь нельзя сделать не через з/п в отличии от гланд.
А зачем? Ну во-первых чисто академический интерес. Во-вторых возникла реальная задача такого плана.

> GuAV ©   (10.09.04 21:07) [15]

Это не С++.

> Verg ©   (10.09.04 21:33) [16]
> > Фиксированый параметр для va_start есть. Необязательные
> > параметры и их колл. вам и знать не надо - это знает только
> > создатель f2.
> > Все что надо - известно.
> Так ты о чем же собственно?
> Умных слов-загадок потолкать или что? :))

Не понял, что ты конкретно не понял. :)
> DiamondShark ©   (11.09.04 11:01) [17]
> Внутри функции невозможно узнать количество переданных параметров,
> функция об этом должна догадываться какими-то шаманскими
> методами (например, интерпретируя значение фиксированных
> параметров, но точное угадывание никто не гарантирует).

А нам и не нужно знать колл. параметров. Мы ж их не юзаем. Просто передает. Все что надо - знать их сумарный размер.

> Поэтому решение может быть примерно такое: погадать по звёздам
> о длине переданных параметров, ассемблерной вставкой переписать их в стек и вызвать функцию.

Вот-вот. Подозреваю единственное решение - копирование стека. Но как его сделать?

> Артем Запаранюк ©   (11.09.04 17:56) [18]

Мы не знаем не только колл. но и типы параметров.

---
У ф-ций стандартной библиотеки ввода-вывода есть ф-ции ...printf и соотв. им эквиваленты v...printf, которые принимают явный список параметров va_list. Если бы был простой способ передачи, то их бы просто не было.
---
Сдается мне что нашел таки первые грабли С++ :-(


 
wicked ©   (2004-09-12 17:51) [20]

> Igorek ©   (12.09.04 15:19) [19]

> У ф-ций стандартной библиотеки ввода-вывода есть ф-ции ...printf
> и соотв. им эквиваленты v...printf, которые принимают явный
> список параметров va_list. Если бы был простой способ передачи,
> то их бы просто не было.

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


> Сдается мне что нашел таки первые грабли С++ :-(

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


 
wicked ©   (2004-09-12 18:08) [21]

гых... раз уж речь зашла о printf"ах, то могу порекомендовать такие прототипы функций:
1. void f1(char * mask, ...);
делает всё что необходимо делать порядочной функции по имени f1, затем формирует va_list на свои переменные аргументы и передает управление ф-ции real_f2....
2. void f2(char * mask, ...);
просто формирует va_list на свои переменные аргументы и передает управление ф-ции real_f2....
3. void real_f2(char * mask, va_list arglist);
делает всё, что должна была делать ф-ция f2....

теперь перейдем к мистическому параметру mask... в него мы должны передать строку, каждый символ которой будет говорить функции о типа параметра, а позиция сего символа в строке - о порядковом номере аргумента... например:
int i, j;
double c, d;
char * string;
... // какой нибудь код....
f1("sidid", string, i, d, j, c);
... // еще какой нибудь код....
f1("ddii", c, d, j, i);


надеюсь, идея ясна?...

ЗЫ а вообще то, такие вещи не решаются чисто языковыми средствами, даже если уж так приспичило...


 
Igorek ©   (2004-09-12 19:07) [22]

> wicked ©   (12.09.04 17:51) [20]
> сори, но зачем перекладывать с больной головы на здоровую?...
> эти, так сказать, грабли присущи будут всем языкам со строгой
> типизацией аргументов...

При чем тут строгая типизация? И чем поможет нестрогая? Приведи пример языка с нестрогой типизацией, переменным колличеством аргументов ф-ции и реши на нем поставленную задачу.
Массивы вариантов - не в счет. :-)

> то, что это хоть как-то реализовано в делфи
А как это реализовано в Дельфи? Насколько я знаю вообще не реализовано. :)

> надеюсь, идея ясна?...
Понятно, но в сабже задача общего плана. А пример с printf я привел как непрямой довод о невозможности решения.

В задаче сказано

> Написать ф-цию
> void f1(int x...) { f2(???); },
> которая вызывала бы
> void f2(int x...) {}
> и передавала все свои аргументы ей.

Т.е.
1) сигнатуры полностью совпадают
2) есть переменное колл. аргументов

Хорошо конечно что в языке С++ есть переменное колл. аргументов. И понятно, что ф-ция, которая их принимает должна сама вырулить сколько их и каковы типы.
Но почему нельзя в общем случае все это передать другой ф-ции - непонятно.
Имхо - грабли.


 
DiamondShark ©   (2004-09-12 19:52) [23]


> А нам и не нужно знать колл. параметров. Мы ж их не юзаем.
> Просто передает. Все что надо - знать их сумарный размер.


А без разницы. Всё равно ни того ни другого не известно.


> > Поэтому решение может быть примерно такое: погадать по
> звёздам
> > о длине переданных параметров, ассемблерной вставкой переписать
> их в стек и вызвать функцию.
>
> Вот-вот. Подозреваю единственное решение - копирование стека.
> Но как его сделать?

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


> Но почему нельзя в общем случае все это передать другой
> ф-ции - непонятно.
> Имхо - грабли.

Ц и есть одни сплошные грабли.


 
Verg ©   (2004-09-12 20:03) [24]


> Ц и есть одни сплошные грабли.


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

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


 
DiamondShark ©   (2004-09-12 20:12) [25]


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

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


 
Igorek ©   (2004-09-12 20:53) [26]

> DiamondShark ©   (12.09.04 19:52) [23]
> > А нам и не нужно знать колл. параметров. Мы ж их не юзаем.
> > Просто передает. Все что надо - знать их сумарный размер.
> А без разницы. Всё равно ни того ни другого не известно.

Не без разницы. Компилятор знает смещение и размер. По моему логично было бы позволить вызов вида f2(x, ...).
Т.е. "..." можно рассматривать как лексический элемент, указывающий на произвольное колл. параметров, и не определенный в теле функции с сигнатурой без "...".

> Ну, если размер выяснить удалось, то уже просто: они находятся сплошным блоком начиная с фиксированного параметра.

В общем случае мы не знаем размер. В отличии от компилятора.

> Ц и есть одни сплошные грабли.
Мягко говоря не согласен.

> Verg ©   (12.09.04 20:03) [24]
> DiamondShark ©   (12.09.04 20:12) [25]

Хорош демагогить! :-)
Больше конкретики.


 
DiamondShark ©   (2004-09-12 21:20) [27]


> Не без разницы. Компилятор знает смещение и размер. По моему
> логично было бы позволить вызов вида f2(x, ...).

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


> В общем случае мы не знаем размер. В отличии от компилятора.

Компилятор его тоже не знает.
В точке вызова знает, внутри функции -- нет.
Компилятор эту информацию мог бы знать, если бы, скажем, в функцию передавались -- как скрытые параметры -- число или длина параметров. Но эта информация не передаётся.


 
Verg ©   (2004-09-12 21:29) [28]


> [26] Igorek ©   (12.09.04 20:53)


С каких пирогов ты на своем трепе хочешь конкретики. Какой?
Ты что-то имеешь предложить или, ... ?


> Не без разницы. Компилятор знает смещение и размер. По моему
> логично было бы позволить вызов вида f2(x, ...).
> Т.е. "..." можно рассматривать как лексический элемент,
> указывающий на произвольное колл. параметров, и не определенный
> в теле функции с сигнатурой без "...".


Хорошь пустомелить! :-()


 
wicked ©   (2004-09-12 22:13) [29]

> Igorek [22]

> Т.е.
> 1) сигнатуры полностью совпадают
> 2) есть переменное колл. аргументов

я дико извиняюсь, но чем не угодили сигнатуры в [21]:
> 1. void f1(char * mask, ...);
> 2. void f2(char * mask, ...);

как видим, они идентичны, а то, что эти функции делают "под водой", это их личные заботы....

> Но почему нельзя в общем случае все это передать другой
> ф-ции - непонятно.

можно - va_list...
если по-си++"ному (по-модному) - реализовать в классе COM-интерфейс IDispatch и передавать всё через аргументы Invoke... такой себе VBA в миниатюре... ;)

> Приведи пример языка с нестрогой типизацией, переменным
> колличеством аргументов ф-ции и реши на нем поставленную
> задачу.

повторю еще раз - PERL...

> Понятно, но в сабже задача общего плана. А пример с printf
> я привел как непрямой довод о невозможности решения.

возможно... но Анголообразные языки в общем то разрабатывались без нацела на фичи, которые вдруг когда-то кому-то понадобятся - если язык не предоставляет какого-либо механизма, то этот механизм можно реализовать, как библиотеку....
а если хочется умного компилятора, то советую приглядеться к Lisp"у и/или Prolog"у...

> Verg [24]
хы-хы.... :)


 
wicked ©   (2004-09-12 22:15) [30]

блин....
> wicked [29]
Анголообразные = Алголообразные...


 
False_Delirium ©   (2004-09-12 23:15) [31]

wicked [29]

Чтобы Perl затрагивать нужно знать как он хранит данные, к какому типу приводит все переменные. А потом уже ставить его в пример. Он только благодаря своему механизму позволяет передавать в ф-ции переменное кол-во параметров.

И в конечном этоге Perl - это "обкрутка" механизмов С. Если уж так говорить, то нужно ставить вопрос о разработке интерпритируемой системы, которая позволяла бы передавать своим ф-циям переменное кол-во параметров.


 
wicked ©   (2004-09-12 23:22) [32]

> False_Delirium [31]
перл я видел издалека... спасибо за науку... :)


 
Igorek ©   (2004-09-13 11:48) [33]

> Verg ©   (12.09.04 21:29) [28]
> > [26] Igorek ©   (12.09.04 20:53)
> С каких пирогов ты на своем трепе хочешь конкретики.
> Хорошь пустомелить! :-()

Тебе наверно за последнее мастера дали.


> DiamondShark ©   (12.09.04 21:20) [27]
> Компилятор его тоже не знает.
> В точке вызова знает, внутри функции -- нет.

Тут ты прав. Но мы углубились в тонкости реализации компилятора. Хотя можно придумать выход из ситуации. Я стараюсь проанализировать (...) с высокоуровневой точки зрения.

> wicked ©   (12.09.04 22:13) [29]

Я прошу прощения, но вы невнимательно читаете мои посты.

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


 
Игорь Шевченко ©   (2004-09-13 11:53) [34]

Между прочим, printf и ей подобные считают количество нужных аргументов исключительно по строке формата...Можно передать в printf много аргументов, если в строке формата ссылок на них не будет, то printf ничего про них не узнает.
va_list - всего лишь адрес аргумента в стеке.


 
DiamondShark ©   (2004-09-13 13:35) [35]


> Но мы углубились в тонкости реализации компилятора. Хотя
> можно придумать выход из ситуации. Я стараюсь проанализировать
> (...) с высокоуровневой точки зрения.

С высокоуровневой точки зрения, средства доступа к параметрам должны быть частью языка. Макросы va_list, va_arg, etc -- средства внеязыковые, и основаны именно на тонкостях реализации компилятора.


 
Странник ©   (2004-09-13 13:49) [36]

нечто подобное реализовано в Clipper"е, но с ограничениями.


 
DiamondShark ©   (2004-09-13 13:54) [37]


> если в строке формата ссылок на них не будет, то printf
> ничего про них не узнает.

Гораздо интереснее, если в строке формата они есть, а вот переданы не будут.


 
Игорь Шевченко ©   (2004-09-13 13:59) [38]

DiamondShark ©   (13.09.04 13:54) [37]


> Гораздо интереснее, если в строке формата они есть, а вот
> переданы не будут.


При этом в большинстве случаев будет либо Access Violation, если указан строковый спецификатор формата, либо случайные числа, если указаны числовые спецификаторы формата.

Я свой пример с printf привел к тому, что вызываемой функции необходимо каким-то образом сообщать, сколько же параметров ей надо принимать во внимание :)



Страницы: 1 вся ветка

Текущий архив: 2004.10.03;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.079 c
3-1094126127
REA
2004-09-02 15:55
2004.10.03
Перехват ошибок IB


1-1095162197
Master Kolyan
2004-09-14 15:43
2004.10.03
Проблема с поисом незарезервированых идентификаторов.


1-1095691197
Goga
2004-09-20 18:39
2004.10.03
Управление объектом


14-1094822954
jack128
2004-09-10 17:29
2004.10.03
Как скопировать содержимое окна CPU


1-1095250634
bloodman
2004-09-15 16:17
2004.10.03
Как пройтись по всем компонентам на форме в рантайм.