PMT>При её вызове в некоторых местах мне не нужно передавать ей _1, _2 и _3 для заполнения, лишь _4. Однако из-за того, что в качестве параметров используются указатели, мне всё равно приходится создавать дополнительные переменные:
PMT>
PMT>std::size_t _1;
PMT>float _2;
PMT>double _3;
PMT>int _4; // Единственная важная для нас переменная в данном случае
PMT>foo(&_1, &_2, &_3, &_4);
PMT>
Передавай NULL, а внутри функции проверяй, если переменная != NULL, то работай с ней, а иначе — ничего не делай.
Здравствуйте, PlusMyTwitterFace, Вы писали:
AN>>Передавай NULL, а внутри функции проверяй, если переменная != NULL, то работай с ней, а иначе — ничего не делай.
PMT>Функции принадлежат библиотеке, которую, разумеется, писал не я.
Делаешь функцию-обвертку над библиотечной и все дела!
void my_foo(size_t *a, float *b, double *c, int *d)
{
size_t dummyA;
float dummyB;
double dummyC;
int dummyD;
if (NULL == a)
a = &dummyA;
if (NULL == b)
b = &dummyB;
if (NULL == c)
c = &dummyC;
if (NULL == d)
d = &dummyD;
foo(a, b, c, d);
}
Здравствуйте, watch-maker, Вы писали:
WM>static DummyPtrFactory _;[/ccode]
int d;
WM> foo(_, _, _, &d); // передаём только четвёртый аргумент
WM>
WM>Хотя, конечно, это может привести к проблемам с многопоточностью, как и при использование любых сложных объектов у которых есть неконстистентные состояния.
Можно совместить оба подхода, при этом довольно дёшево.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
F>>Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор).
E>Чушь, ботай value initialization.
Сами сначала изучите "value initialization".
F>>Более того, он не корректен для С. E>И что с того?
Ничего, все
E>Да, вариант с агрегатом сбивает оптимизаторы. Например, оптимизатор MSVC...
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>- Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.
А кто тебе сказал что это ошибка? (порядок вызова от этого не меняется)
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>- Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.
не пофиг ли?
PMT>- gcc 4.7.1 не компилирует assert'ы в данном коде. Пока не вникал в суть ошибок.
#include <assert.h> типа...
Но уровень дискуссии доставляет. Ты правда не знаешь, что такое assert?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
В данном случае всё равно.
E>Но уровень дискуссии доставляет. Ты правда не знаешь, что такое assert?..
Не понял. К чему этот вопрос и с чего он возник? Вы думаете, что я не в состоянии включить cassert / assert.h?
Ошибки, на самом деле, возникали в связи с -Wall -Werror, с которыми я запускал gcc, из-за всё того же порядка инициализации. Про assert показалось, просто рядом было.
Здравствуйте, Sni4ok, Вы писали:
К>>Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль.
S>чё за бред, по вашему и strlen на 0 проверяет?
Всё верно. Некоторые кривые сторонние библиотеки этого не делают.
При её вызове в некоторых местах мне не нужно передавать ей _1, _2 и _3 для заполнения, лишь _4. Однако из-за того, что в качестве параметров используются указатели, мне всё равно приходится создавать дополнительные переменные:
std::size_t _1;
float _2;
double _3;
int _4; // Единственная важная для нас переменная в данном случае
foo(&_1, &_2, &_3, &_4);
Вызывать такие функции приходится довольно много раз, в связи с чем создание лишних переменных каждый раз — не самая лучшая идея (увеличивается объём кода и визуально более сложно понять, какая из переменных нам на самом деле нужна).
В C99 и C11 эту проблему можно решить при помощи compound literals:
— Создать отдельную функцию foo_wrapper, которая будет создавать "лишние аргументы" на своей стороне, а в качестве аргумента принимать лишь действительно необходимый. Не самый лучший вариант, поскольку в разные моменты времени "необходимыми" бывают совершенно разные аргументы. Более того, таких функций достаточно много, и писать для каждой из них такие врапперы не самая лучшая идея.
— Создать в file_scope переменные всех фундаментальных типов с приставкой "dummy", которые, собственно, и будут использоваться для передачи в такие функции. Также не самый лучший вариант — лишнее засорение глобального пространства имён. Кроме того, в подобные функции иногда передаются даже User-defined types, а писать dummy-версии для каждого типа, используемого в программе — это какой-то ужас.
Передаваться нули тоже не вариант — никто не гарантирует, что внутри этих функций будут сделаны соответствующие проверки.
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
PMT>Например, есть у меня, допустим, функция со следующим объявлением:
PMT>При её вызове в некоторых местах мне не нужно передавать ей _1, _2 и _3 для заполнения, лишь _4. Однако из-за того, что в качестве параметров используются указатели, мне всё равно приходится создавать дополнительные переменные:
Как-то так:
template<typename T>
class _
{
public:
operator T*() const { return v_; }
private:
T v_;
};
…
int four;
foo(_<size_t>(), _<float>(), _<double>(), &four);
Интересно было бы добиться синтаксиса foo(_, _, _, &four) для любого типа (с использованием шаблонного operator T*?) и при этом сохранить автоматическую деструкцию ненужного объекта.
Здравствуйте, Centaur, Вы писали:
C>Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции? PMT>Например, есть у меня, допустим, функция со следующим объявлением:
PMT>Передаваться нули тоже не вариант — никто не гарантирует, что внутри этих функций будут сделаны соответствующие проверки.
Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль. Для остального есть возможность передавать по ссылке.
Разве только это библиотечный код, который нельзя менять.
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
PMT>Например, есть у меня, допустим, функция со следующим объявлением:
PMT>
nullptr уже предлагали.
PMT>на своей стороне, а в качестве аргумента принимать лишь действительно необходимый. Не самый лучший вариант, поскольку в разные моменты времени "необходимыми" бывают совершенно разные аргументы.
Ну сделай несколько врапперов. Делов-то.
PMT> Более того, таких функций достаточно много
и?
> Создать в file_scope переменные всех фундаментальных типов с приставкой "dummy", которые, собственно, и будут использоваться для передачи в такие функции
я б не стал этого делать ни в коем случае.
Во-первых, многопоточность. Ну объявишь ты `std::vector<int> dummy_vector_int`, а вдруг два потока захотят её использовать. А вдруг два потока одновременно её изменят. Тут и сложно отлавливаемый сегфолт в лицо получить можно.
Во-вторых, это расстроит оптимизатор. Например:
int dummy_a;//даммиint z1(int* z){*z = 1;} //ф-ция не все аргументы мы хотим использовать.int c(){ //мы здесь
z1(dummy_a);//dummy_a=1, используем глобальнуюint x;
z1(x);//x=1, используем локальную
}
z1 заинлайнится. Теперь такое дело — x=1 можно выкиунть, ибо dead code и x никем не считывается. Мы не можем сказать то же самое про dummy_a=1, так как у нас тупо нет сведений, что она никем не используется.
То есть фактически при использовании глобальных объектов получится менее оптимальный код.
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>- Создать в file_scope переменные всех фундаментальных типов с приставкой "dummy", которые, собственно, и будут использоваться для передачи в такие функции. Также не самый лучший вариант — лишнее засорение глобального пространства имён. Кроме того, в подобные функции иногда передаются даже User-defined types, а писать dummy-версии для каждого типа, используемого в программе — это какой-то ужас.
Dummy заглушки можно почти автоматически создавать:
int d;
foo(_, _, _, &d); // передаём только четвёртый аргумент
Хотя, конечно, это может привести к проблемам с многопоточностью, как и при использование любых сложных объектов у которых есть неконстистентные состояния.
C>Интересно было бы добиться синтаксиса foo(_, _, _, &four) для любого типа (с использованием шаблонного operator T*?) и при этом сохранить автоматическую деструкцию ненужного объекта.
Потоко-небезопасное решение со скрытыми статическими переменными:
если функций о-о-о-чень много, то можно написать, в принципе, набор функций ptr_bind_XoXo, ptr_bind_oXoX, и т. д. которые бурут на вход указатель на целевую функцию, а возвращают функтор, с профильтрованными полями
Типа будет как-то так:
auto foo_oXoX = ptr_bind_oXoX( foo );
foo_oXoX( arg2, arg4 )
Ну и, наконец, есть ещё один смешной вариант.
Написать такую примерно, штуку
// name1 - name4 какие-то предъобъявленные id, либо числа, либо типы, не суть важно, на самом делеauto foo_ = call_with_optional_ptrs<name1, name2, name3, name4>( foo );
foo_( param<name2>( p2 ) & param<name4>( p4 ) );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>А ничего, что таких врапперов мне придётся тогда написать, скажем, 200?
Это дело можно автоматизировать, вообще-то.
У тебя сколько функций и сколько "паттернов" пропуска аргументов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
PMT>>Например, есть у меня, допустим, функция со следующим объявлением:
PMT>>
Здравствуйте, PlusMyTwitterFace, Вы писали:
К>>Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль
PMT>Не хотелось бы на это просто рассчитывать.
А что про передачу NULL в качестве параметра этой функции говорит документация по библиотеке?
PARAM param = PARAM();
// установи нужные поля. Остальные будут NULL.
foo(¶m);
верно компилируется сильно не всеми компиляторами, так что, формально, прав, конечно же ты, а вот на практике, код Дворкина возможно таки и попереносимее может оказаться...
Хотя бываеют, конечно, контроллеры, в которых нулевой бинароно указатель вполне валиден
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>В C99 и C11 эту проблему можно решить при помощи compound literals:
PMT>В C++ на ум приходит лишь два решения:
А что за С++? 03 или можно 11?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
> Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
В бусте кстати есть библиотека поддержки именованных параметров.
Используется в boost::graph. Но саму библиотеку я забыл.
Можеш либо использовать, либо стянуть идею.
Здравствуйте, Erop, Вы писали:
F>>NULL не всегда равен 0! Ваш код не переносим.
E>К сожалниею, переносимый код
E>PARAM param = PARAM();
E>// установи нужные поля. Остальные будут NULL.
E>foo(¶m);
верно компилируется сильно не всеми компиляторами, так что, формально, прав, конечно же ты, а вот на практике, код Дворкина возможно таки и попереносимее может оказаться... E>Хотя бываеют, конечно, контроллеры, в которых нулевой бинароно указатель вполне валиден
Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор). Более того, он не корректен для С.
Здравствуйте, freestyle, Вы писали:
F>Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор).
Чушь, ботай value initialization.
F>Более того, он не корректен для С.
И что с того?
Да, вариант с агрегатом сбивает оптимизаторы. Например, оптимизатор MSVC...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, PlusMyTwitterFace, Вы писали:
M>>Ну сделай несколько врапперов. Делов-то.
PMT>Как я уже сказал выше, данные функции принадлежат библиотеке.
Ну и? Пускай принадлежат.
M>>и?
PMT>А ничего, что таких врапперов мне придётся тогда написать, скажем, 200?
Ты намерен использовать все 200 врапперов? Если нет(а я уверен, что нет), то не пиши 200. Делов-то
Спасибо за совет, ознакомлюсь с Вашей реализацией.
Есть, правда, пара моментов:
— Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.
— gcc 4.7.1 не компилирует assert'ы в данном коде. Пока не вникал в суть ошибок.
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>В данном случае всё равно. PMT>Не понял. К чему этот вопрос и с чего он возник? Вы думаете, что я не в состоянии включить cassert / assert.h?
Ну раньше думал, что в состоянии, но теперь не уверен...
PMT>Ошибки, на самом деле, возникали в связи с -Wall -Werror, с которыми я запускал gcc, из-за всё того же порядка инициализации. Про assert показалось, просто рядом было.
На самом деле это был код, написанный для демонстрации концепции, он вообще не обязан компилироваться...
Но уровень дискуссии всё равно доставляет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Прада, если делать это всё законченным решением, то нехило бы поддержать ещё и буфера.
Например, можно приписать operator[], которому в аргумент передаёют размер буфера, а он возвращает аналог или наследник CFakeArgument, который по operator T*() аллокирует буфер нужного размера. Правда всё раво не ясно, что делать с T**, которые обычно используются для того, что бы передать указатель на буфер, который будет аллокирован внутри функции и возвращён наружу, так как есть, как минимум два популярных способа его разрушения. Через free и через delete[]...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Sni4ok, Вы писали:
S>чё за бред, по вашему и strlen на 0 проверяет?
Я думаю, что имелись в виду факультативные параметры...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
ндя.... прочитал все и так понял, что не удивительно, что у нас год от года все больше гигарец и гигабайт доступно, но проги все больше и больше тупят и тормозят...
уважаемый PlusMyTwitterFace: писать самое главное надо просто — и если вам что-то не нравиться в чем-то — это не повод изобретать велики и носки-самокаты с нуля. И все уважаемые советчики — нахрена в данной ситуации вы даже просто позволили себе подумать — А КАК эту задачу можно решать по другому? Нахрена городить уйму строк с шаблонами и черт-еще-знает-чем? Просто потому что С++ это позволяет — а вы решили что так можно написать?
Простейшая ситуация, когда надо задать только последний параметр в функции превратилась просто в монстра по решениям. Вам не страшно потом этот ужас поддерживать? Исправлять? Передавать, так сказать, по наследству кому-то?
Вот ответьте сперва на главнейший вопрос — нафига в вопросе, заданном PlusMyTwitterFace вообще искать какое-то новое решение?
Кто и главное КАК выиграет от нового решения? и в чем?
Здравствуйте, Centaur, Вы писали:
C>Здравствуйте, DestinyChild, Вы писали:
DC>>нахрена в данной ситуации вы даже просто позволили себе подумать[…]?
C>Потому что можем.
можем что? просто написать кучу кода, который компилируется и не падает?
а нафига? это важный вопрос — а на него походу никто ответа не знает)))
в данном случае ничего не надо делать. просто подать пустые переменные,
да не используются, да, место занимают, но:
1. короче чем 3 доп. строки общей длиной в символов 15 вы так и не дали решения.
тока увеличили раз в 10.
2. понимания с первого прочтения новый "расширенный" код не дает. Тока путает.
Кому от этого в этом случае станет легче? никому.
3. к 100% идентично-верному решению не подошел ни один из участников топика,
что означает, что доподлинно никто не знает верного решения, а решение, которое
вы формируете тут на ходу — все в подводных камнях и проблемах. В то время как
решение с доп.переменными 100% рабочее и верное.
Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
1.Для User-defined, часто используемых и требующих громоздкой инициализации,
сделать производные типы, создающие объекты по умолчанию.
2.Разобраться в логике этих функций и сделать адаптеры для сокращения кода.
Больше никаким образом, и это не связано со спецификой языка.
Здравствуйте, DestinyChild, Вы писали:
DC>Здравствуйте, Centaur, Вы писали:
C>>Здравствуйте, DestinyChild, Вы писали:
DC>>>нахрена в данной ситуации вы даже просто позволили себе подумать[…]?
DC>можем что? просто написать кучу кода, который компилируется и не падает? DC>а нафига? это важный вопрос — а на него походу никто ответа не знает))) DC>в данном случае ничего не надо делать. просто подать пустые переменные,
Вы очень эмоционально здесь так о всем сразу (эмоции видны по выражениях-усилителей: нахрена, кучу, 100% и т.д.). Просто бы написали, что на ваш взгляд ничего страшного в использовании "dummy" переменных — нет. И, например, я, с этой точкой зрения согласен. Но я не согласен с остальными вашими рассуждениями.
DC>1. короче чем 3 доп. строки общей длиной в символов 15 вы так и не дали решения. DC>тока увеличили раз в 10.
В худшем случаи, на каждое применение функции foo требуется 3 дополнительных строчки кода. То есть, для 100 применений будет требоваться уже 300 строчек кода.
По этому на мой взгляд — это не аргумент.
DC>2. понимания с первого прочтения новый "расширенный" код не дает. Тока путает. DC>Кому от этого в этом случае станет легче? никому.
Действительно, то что здесь предлагали используя С++ — глупости. Но не потому что много непонятного кода (это абсолютно неважно, так как его можно скрыть), а потому что решают не ту задачу! Проблема не в том как бы упростить подстановку "dummy" переменной, а в том что функция foo не позволяет "игнорировать" свои параметры.
DC>3. к 100% идентично-верному решению не подошел ни один из участников топика, DC>что означает, что доподлинно никто не знает верного решения, а решение, которое DC>вы формируете тут на ходу — все в подводных камнях и проблемах. В то время как DC>решение с доп.переменными 100% рабочее и верное.
На мой взгляд, другое правильное решение (кроме того что вы предложили) — это передавать в foo NULL или если это невозможно — доопределить foo так что-бы ей можно было передавать NULL.
Но, какое из этих решение нужно использовать — зависит от более детального понимания ситуации проекта PlusMyTwitterFace.
DC>Вот ответьте сперва на главнейший вопрос — нафига в вопросе, заданном PlusMyTwitterFace вообще искать какое-то новое решение?
Потому, что оно лучше.
Смотри, например, сюда: http://users.livejournal.com/_winnie/229311.html
DC>Кто и главное КАК выиграет от нового решения? и в чем?
Код станет проще, понятнее, будет лучше поддерживаться и всё такое...
А если тебя смутила задачка, как сделать так, что бы _ сам разрешался в то, в что надо, то это просто прикольный простенький этюд... К собственно задаче ТС прямого отношения не имеет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском