При её вызове в некоторых местах мне не нужно передавать ей _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*?) и при этом сохранить автоматическую деструкцию ненужного объекта.
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, то работай с ней, а иначе — ничего не делай.
Здравствуйте, 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*?) и при этом сохранить автоматическую деструкцию ненужного объекта.
Потоко-небезопасное решение со скрытыми статическими переменными:
Здравствуйте, watch-maker, Вы писали:
WM>static DummyPtrFactory _;[/ccode]
int d;
WM> foo(_, _, _, &d); // передаём только четвёртый аргумент
WM>
WM>Хотя, конечно, это может привести к проблемам с многопоточностью, как и при использование любых сложных объектов у которых есть неконстистентные состояния.
Можно совместить оба подхода, при этом довольно дёшево.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
если функций о-о-о-чень много, то можно написать, в принципе, набор функций 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?
Это дело можно автоматизировать, вообще-то.
У тебя сколько функций и сколько "паттернов" пропуска аргументов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, 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);
}
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, PlusMyTwitterFace, Вы писали:
PMT>>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?
PMT>>Например, есть у меня, допустим, функция со следующим объявлением:
PMT>>