Re: Как избавиться от лишних аргументов
От: AleksandrN Россия  
Дата: 25.09.12 05:47
Оценка: 2 (2) +2
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Например, есть у меня, допустим, функция со следующим объявлением:


PMT>
PMT>void foo(std::size_t* _1, float* _2, double* _3, int* _4);
PMT>


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, то работай с ней, а иначе — ничего не делай.
Re[3]: Как избавиться от лишних аргументов
От: freestyle  
Дата: 25.09.12 19:00
Оценка: 3 (1) +1
Здравствуйте, 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);
}
Re[2]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 25.09.12 16:38
Оценка: 1 (1) +1
Здравствуйте, watch-maker, Вы писали:

WM>static DummyPtrFactory _;[/ccode]
    int d;
WM>    foo(_, _, _, &d); // передаём только четвёртый аргумент
WM>

WM>Хотя, конечно, это может привести к проблемам с многопоточностью, как и при использование любых сложных объектов у которых есть неконстистентные состояния.


Можно совместить оба подхода, при этом довольно дёшево.
class CFakeArgument {
    typedef double alignAs_t; // можно прагамами, С++11 или ещё как замутить, не суть.
    enum { bufSize = 32 }; // В общем сколько стеку не жаль
    
    struct CBuffer {
        alignAs_t alignPad;
        char bytes[bufSize - sizeof( alignAs_t )];
    } buffer;

    typedef  void deleter_t( void* );
    deleter_t* deleter;
    void* data;
    
    CFakeArgument( const CFakeArgument& );
    void operator = ( const CFakeArgument& ); // = delete
    
    //    Полиморфная часть
    template<typename T> 
    struct CData {
        T Data;
        
        void* operator new( size_t size, CBuffer& dstBuffer )
        {
            if( sizeof( CData ) <= bufSize ) {
                assert( size <= bufSize );
                return &dstBuffer;
            } else {
                return ::new char[size];
            }
        }

        void operator delete( void* p, CBuffer& dstBuffer )
        {
            if( sizeof( CData ) <= bufSize ) {
                assert( p == 0 || p == &dstBuffer );
            } else {
                ::delete[] (char*)p;
            }
        }

        void operator delete( void* p )
        {
            if( sizeof( CData ) > bufSize ) {
                ::delete[] (char*)p;
            }
        }

        static void deleter( void* p )
        {
            delete static_cast<CData*>( p );
        }
        
        T& Save( void*& thisStorage, deleter_t*& deleterStorage )
        {
            assert( thisStorage == 0 && deleterStorage == 0 );
            thisStorage = this;
            deleterStorage = deleter;
            return Data;
        }
    };


public:
    CFakeArgument() : data( 0 ), deleter( 0 ) {};
    ~CFakeArgument() { if(deleter != 0 ) deleter( data ); }
    
    template<typename T>
    operator T&()
    {
        if( data == 0 ) {
            return ( new( buffer ) CData<T> )-> Save( data, deleter );
        } else {
            assert( deleter == CData<T>::deleter );
            return static_cast<CData<T>*>(data)->Data;
        }
    }
    template<typename T>
    operator T*() { return &(T&)(*this); }
};

#define _0_ CFakeArgument() 
/////////////////////////
//  Проверка
struct BigStruct { int Field[100]; };
void foo( int*, BigStruct*, char* ) {}
void bar() { foo( _0_, _0_, _0_ );}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Как избавиться от лишних аргументов
От: Centaur Россия  
Дата: 29.09.12 13:18
Оценка: +1 :)
Здравствуйте, DestinyChild, Вы писали:

DC>нахрена в данной ситуации вы даже просто позволили себе подумать[…]?


Потому что можем.
Re[6]: Как избавиться от лишних аргументов
От: freestyle  
Дата: 26.09.12 11:00
Оценка: -1
Здравствуйте, Erop, Вы писали:

F>>Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор).


E>Чушь, ботай value initialization.


Сами сначала изучите "value initialization".

F>>Более того, он не корректен для С.

E>И что с того?

Ничего, все

E>Да, вариант с агрегатом сбивает оптимизаторы. Например, оптимизатор MSVC...


Никто здесь ничего не сбивает.
Re[4]: Как избавиться от лишних аргументов
От: Piko  
Дата: 26.09.12 19:48
Оценка: +1
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>- Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.


А кто тебе сказал что это ошибка? (порядок вызова от этого не меняется)
Re[4]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 26.09.12 20:09
Оценка: :)
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>- Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.


не пофиг ли?

PMT>- gcc 4.7.1 не компилирует assert'ы в данном коде. Пока не вникал в суть ошибок.

#include <assert.h> типа...

Но уровень дискуссии доставляет. Ты правда не знаешь, что такое assert?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 26.09.12 20:21
Оценка: -1
E>не пофиг ли?

В данном случае всё равно.

E>Но уровень дискуссии доставляет. Ты правда не знаешь, что такое assert?..


Не понял. К чему этот вопрос и с чего он возник? Вы думаете, что я не в состоянии включить cassert / assert.h?

Ошибки, на самом деле, возникали в связи с -Wall -Werror, с которыми я запускал gcc, из-за всё того же порядка инициализации. Про assert показалось, просто рядом было.
Re[3]: Как избавиться от лишних аргументов
От: Константин Россия  
Дата: 30.09.12 16:24
Оценка: :)
Здравствуйте, Sni4ok, Вы писали:

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


S>чё за бред, по вашему и strlen на 0 проверяет?


Всё верно. Некоторые кривые сторонние библиотеки этого не делают.
Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 25.09.12 03:44
Оценка:
Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?

Например, есть у меня, допустим, функция со следующим объявлением:

void foo(std::size_t* _1, float* _2, double* _3, int* _4);


При её вызове в некоторых местах мне не нужно передавать ей _1, _2 и _3 для заполнения, лишь _4. Однако из-за того, что в качестве параметров используются указатели, мне всё равно приходится создавать дополнительные переменные:

std::size_t _1;
float _2;
double _3;
int _4; // Единственная важная для нас переменная в данном случае

foo(&_1, &_2, &_3, &_4);


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

В C99 и C11 эту проблему можно решить при помощи compound literals:

foo((std::size_t[]){0}, (float[]){0.0f}, (double[]){0.0}, &_4);


В C++ на ум приходит лишь два решения:

— Создать отдельную функцию foo_wrapper, которая будет создавать "лишние аргументы" на своей стороне, а в качестве аргумента принимать лишь действительно необходимый. Не самый лучший вариант, поскольку в разные моменты времени "необходимыми" бывают совершенно разные аргументы. Более того, таких функций достаточно много, и писать для каждой из них такие врапперы не самая лучшая идея.

— Создать в file_scope переменные всех фундаментальных типов с приставкой "dummy", которые, собственно, и будут использоваться для передачи в такие функции. Также не самый лучший вариант — лишнее засорение глобального пространства имён. Кроме того, в подобные функции иногда передаются даже User-defined types, а писать dummy-версии для каждого типа, используемого в программе — это какой-то ужас.

Передаваться нули тоже не вариант — никто не гарантирует, что внутри этих функций будут сделаны соответствующие проверки.

Что посоветуете сделать?
Re: Как избавиться от лишних аргументов
От: Centaur Россия  
Дата: 25.09.12 05:00
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


PMT>Например, есть у меня, допустим, функция со следующим объявлением:


PMT>void foo(std::size_t* _1, float* _2, double* _3, int* _4);

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*?) и при этом сохранить автоматическую деструкцию ненужного объекта.
Re[2]: Один из вариантов -- объект-механизм
От: Erop Россия  
Дата: 25.09.12 05:50
Оценка:
Здравствуйте, Centaur, Вы писали:

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


PMT>>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


Может подойдёт
Автор: Erop
Дата: 12.01.07
...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как избавиться от лишних аргументов
От: Константин Россия  
Дата: 25.09.12 06:12
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?

PMT>Например, есть у меня, допустим, функция со следующим объявлением:

void foo(std::size_t* _1, float* _2, double* _3, int* _4);


PMT>Передаваться нули тоже не вариант — никто не гарантирует, что внутри этих функций будут сделаны соответствующие проверки.



Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль. Для остального есть возможность передавать по ссылке.
Разве только это библиотечный код, который нельзя менять.
Re: Как избавиться от лишних аргументов
От: Pavel Dvorkin Россия  
Дата: 25.09.12 10:04
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


PMT>Например, есть у меня, допустим, функция со следующим объявлением:


PMT>
PMT>void foo(std::size_t* _1, float* _2, double* _3, int* _4);
PMT>


PMT>Что посоветуете сделать?



struct PARAM
{
std::size_t _1;
float* _2;
double* _3;
int* _4;
};

void foo(PARAM* param);

// вызов

PARAM param;
memset(&param, 0, sizeof(PARAM);
// установи нужные поля. Остальные будут NULL.
foo(&param);
With best regards
Pavel Dvorkin
Re: Как избавиться от лишних аргументов
От: maykie Россия  
Дата: 25.09.12 10:53
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

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, так как у нас тупо нет сведений, что она никем не используется.

То есть фактически при использовании глобальных объектов получится менее оптимальный код.
Re: Как избавиться от лишних аргументов
От: Сыроежка  
Дата: 25.09.12 11:09
Оценка:
Очевидно, что вам просто нужно перегрузить функцию с нужным количеством аргументов.
Меня можно встретить на www.cpp.forum24.ru
Re[2]: Как избавиться от лишних аргументов
От: watch-maker  
Дата: 25.09.12 12:18
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Интересно было бы добиться синтаксиса foo(_, _, _, &four) для любого типа


Можно, наверно, сделать как-то так:
template <typename T>
class Optional {
protected:
    T Data;
    bool Initialized;
public:
    Optional(): Initialized(false) {}
    Optional(const T& d) : Data(d), Initialized(true) {}
    operator T() {return Data; }
    bool IsSet() const {return Initialized; }
    const T& Get() const { return Data; }
};

struct TH {
    template <class T>
    operator Optional<T>() { return Optional<T>(); }
};
static TH _;

Ну и использовать примерно так:
template <class T>
std::ostream& operator<<(std::ostream& out, const Optional<T>& opt) {
    if (opt.IsSet())
        out << opt.Get();
    else
        out << "{Not set}";
    return out;
}

void foo(Optional<size_t*> a, Optional<float*> b, Optional<double*> c, Optional<int> d) {
    std::cout << "foo(" << a << ", " << b << ", " << c << ", " << d << ")" << std::endl;

    if (a.IsSet())
        *a = 10;
}

int main() {
    size_t a;
    float b;
    double c;
    int d = 42;
    foo(&a, &b, &c, d);
    foo(&a, &b, &c, _);
    foo(_, _, _, d);
    foo(_, _, _, _);
    return 0;
}
Re: Как избавиться от лишних аргументов
От: watch-maker  
Дата: 25.09.12 13:05
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>- Создать в file_scope переменные всех фундаментальных типов с приставкой "dummy", которые, собственно, и будут использоваться для передачи в такие функции. Также не самый лучший вариант — лишнее засорение глобального пространства имён. Кроме того, в подобные функции иногда передаются даже User-defined types, а писать dummy-версии для каждого типа, используемого в программе — это какой-то ужас.


Dummy заглушки можно почти автоматически создавать:
struct DummyPtrFactory {
    template <typename T>
    operator T*() {static T x; return &x; }
};
static DummyPtrFactory _;
    int d;
    foo(_, _, _, &d); // передаём только четвёртый аргумент

Хотя, конечно, это может привести к проблемам с многопоточностью, как и при использование любых сложных объектов у которых есть неконстистентные состояния.
Re[2]: Как избавиться от лишних аргументов
От: rg45 СССР  
Дата: 25.09.12 13:47
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Как-то так:

C>
C>template<typename T>
C>class _
C>{
C>public:
C>    operator T*() const { return v_; }
C>private:
C>    T v_;
C>};
C>…
C>int four;
C>foo(_<size_t>(), _<float>(), _<double>(), &four);
C>

C>Интересно было бы добиться синтаксиса foo(_, _, _, &four) для любого типа (с использованием шаблонного operator T*?) и при этом сохранить автоматическую деструкцию ненужного объекта.

Потоко-небезопасное решение со скрытыми статическими переменными:
struct
{
  template<typename T>
  operator T&() const
  {
    static T t;
    return t;
  }

  template<typename T>
  operator T*() const  
  { 
    return &static_cast<T&>(*this); 
  }

} const _ = {};

void foo(float*, int*, double&, long&);

int main()
{
  foo(_,_,_,_);
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Как избавиться от лишних аргументов
От: Сыроежка  
Дата: 25.09.12 14:03
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Очевидно, что вам просто нужно перегрузить функцию с нужным количеством аргументов.


Например, если у вас нет доступа к телу функции, то можно сделать так



inline void foo( int *p )
{
   std::size_t _1;
   float _2;
   double _3;

   foo(&_1, &_2, &_3, p);
}
Меня можно встретить на www.cpp.forum24.ru
Re[3]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 25.09.12 17:19
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Например, если у вас нет доступа к телу функции, то можно сделать так


С>
С>inline void foo( int *p )
С>{
С>   std::size_t _1;
С>   float _2;
С>   double _3;

С>   foo(&_1, &_2, &_3, p);
С>}
С>


Это дело можно слегка оптимизировать... Лучше всего, конечно, было бы придумать, как сбда привернуть bind, но я пока что не придумал лучше, чем так:
template<typename T> struct TheSame { typedef T Type; }; 
template<typename TRes, typename T1, typename T2, typename T3, typename T4> 
TRes call_oooX( TRes (*f)( T1*, T2*, T3*, T4* ), typename TheSame<T4*>::Type v4 )
{
    T1 v1 = T1();
    T2 v2 = T2();
    T3 v3 = T3();
    return f( &v1, &v2, &v3, v4 );
}

//////////////////
// проверим себя
struct BigStruct { int Field[100]; };
void foo( int*, BigStruct*, char*, int* ) {}
void bar() 
{ 
    call_oooX( foo, 0 ); // и с  литералом работает!
}

если функций о-о-о-чень много, то можно написать, в принципе, набор функций 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 ) );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 25.09.12 18:08
Оценка:
AN>Передавай NULL, а внутри функции проверяй, если переменная != NULL, то работай с ней, а иначе — ничего не делай.

Функции принадлежат библиотеке, которую, разумеется, писал не я.
Re[2]: Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 25.09.12 18:09
Оценка:
К>Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль

Не хотелось бы на это просто рассчитывать.

К>Разве только это библиотечный код, который нельзя менять.


Именно так и есть.
Re[2]: Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 25.09.12 18:13
Оценка:
M>Ну сделай несколько врапперов. Делов-то.

Как я уже сказал выше, данные функции принадлежат библиотеке.

M>и?


А ничего, что таких врапперов мне придётся тогда написать, скажем, 200?
Re[3]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 25.09.12 18:36
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>А ничего, что таких врапперов мне придётся тогда написать, скажем, 200?


Это дело можно автоматизировать, вообще-то.

У тебя сколько функций и сколько "паттернов" пропуска аргументов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Как избавиться от лишних аргументов
От: freestyle  
Дата: 25.09.12 19:07
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


PMT>>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


PMT>>Например, есть у меня, допустим, функция со следующим объявлением:


PMT>>
PMT>>void foo(std::size_t* _1, float* _2, double* _3, int* _4);
PMT>>


PMT>>Что посоветуете сделать?



PD>
PD>struct PARAM
PD>{
PD>std::size_t _1;
PD>float* _2;
PD>double* _3;
PD>int* _4;
PD>};

PD>void foo(PARAM* param);

PD>// вызов

PD>PARAM param;
PD>memset(&param, 0, sizeof(PARAM);
PD>// установи нужные поля. Остальные будут NULL.
PD>foo(&param);

PD>


NULL не всегда равен 0! Ваш код не переносим.
Re[3]: Как избавиться от лишних аргументов
От: AleksandrN Россия  
Дата: 25.09.12 19:27
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

К>>Если функция принимает указатель, то она, вроде бы, обязана проверять на ноль


PMT>Не хотелось бы на это просто рассчитывать.


А что про передачу NULL в качестве параметра этой функции говорит документация по библиотеке?
Re[3]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 25.09.12 20:15
Оценка:
Здравствуйте, freestyle, Вы писали:

PD>>
PD>>struct PARAM
PD>>{
PD>>std::size_t _1;
PD>>float* _2;
PD>>double* _3;
PD>>int* _4;
PD>>};

PD>>void foo(PARAM* param);

PD>>// вызов

PD>>PARAM param;
PD>>memset(&param, 0, sizeof(PARAM);
PD>>// установи нужные поля. Остальные будут NULL.
PD>>foo(&param);

PD>>


F>NULL не всегда равен 0! Ваш код не переносим.


К сожалниею, переносимый код
PARAM param = PARAM();
// установи нужные поля. Остальные будут NULL.
foo(&param);
верно компилируется сильно не всеми компиляторами, так что, формально, прав, конечно же ты, а вот на практике, код Дворкина возможно таки и попереносимее может оказаться...
Хотя бываеют, конечно, контроллеры, в которых нулевой бинароно указатель вполне валиден
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 25.09.12 20:18
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>В C99 и C11 эту проблему можно решить при помощи compound literals:


PMT>В C++ на ум приходит лишь два решения:


А что за С++? 03 или можно 11?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как избавиться от лишних аргументов
От: MasterZiv СССР  
Дата: 25.09.12 20:52
Оценка:
> Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?

В бусте кстати есть библиотека поддержки именованных параметров.
Используется в boost::graph. Но саму библиотеку я забыл.
Можеш либо использовать, либо стянуть идею.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Как избавиться от лишних аргументов
От: freestyle  
Дата: 25.09.12 20:56
Оценка:
Здравствуйте, Erop, Вы писали:

F>>NULL не всегда равен 0! Ваш код не переносим.


E>К сожалниею, переносимый код
E>PARAM param = PARAM();
E>// установи нужные поля. Остальные будут NULL.
E>foo(&param);
верно компилируется сильно не всеми компиляторами, так что, формально, прав, конечно же ты, а вот на практике, код Дворкина возможно таки и попереносимее может оказаться...

E>Хотя бываеют, конечно, контроллеры, в которых нулевой бинароно указатель вполне валиден

Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор). Более того, он не корректен для С.
Re[5]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 26.09.12 01:23
Оценка:
Здравствуйте, freestyle, Вы писали:

F>Ваш вариант тоже не переносим (что бы стал переносим нужно написать свой конструктор "по умолчанию", но это уже другой разговор).


Чушь, ботай value initialization.

F>Более того, он не корректен для С.

И что с того?

Да, вариант с агрегатом сбивает оптимизаторы. Например, оптимизатор MSVC...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как избавиться от лишних аргументов
От: maykie Россия  
Дата: 26.09.12 03:02
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

M>>Ну сделай несколько врапперов. Делов-то.


PMT>Как я уже сказал выше, данные функции принадлежат библиотеке.


Ну и? Пускай принадлежат.

M>>и?


PMT>А ничего, что таких врапперов мне придётся тогда написать, скажем, 200?


Ты намерен использовать все 200 врапперов? Если нет(а я уверен, что нет), то не пиши 200. Делов-то
Re[3]: Как избавиться от лишних аргументов
От: Pavel Dvorkin Россия  
Дата: 26.09.12 07:30
Оценка:
Здравствуйте, freestyle, Вы писали:

F>NULL не всегда равен 0! Ваш код не переносим.


Да, может быть такое. Если рассматривать основные платформы — вполне переносим.
With best regards
Pavel Dvorkin
Re[3]: Как избавиться от лишних аргументов
От: PlusMyTwitterFace  
Дата: 26.09.12 19:42
Оценка:
Спасибо за совет, ознакомлюсь с Вашей реализацией.

Есть, правда, пара моментов:

— Здесь присутствует ошибка с порядком инициализации полей — deleter объявлен в классе раньше data, хотя инициализируется в списке инициализации конструктора позже.

— gcc 4.7.1 не компилирует assert'ы в данном коде. Пока не вникал в суть ошибок.
Re[6]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 26.09.12 20:29
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>В данном случае всё равно.

PMT>Не понял. К чему этот вопрос и с чего он возник? Вы думаете, что я не в состоянии включить cassert / assert.h?

Ну раньше думал, что в состоянии, но теперь не уверен...

PMT>Ошибки, на самом деле, возникали в связи с -Wall -Werror, с которыми я запускал gcc, из-за всё того же порядка инициализации. Про assert показалось, просто рядом было.


На самом деле это был код, написанный для демонстрации концепции, он вообще не обязан компилироваться...
Но уровень дискуссии всё равно доставляет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 28.09.12 12:28
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Спасибо за совет, ознакомлюсь с Вашей реализацией.

PMT>Есть, правда, пара моментов:

Кстати, я добрался до компилятора, и проверил чего там и как, и нашёл ошибку.
у шаблона структуры CFakeArgument::CData не хватает специализации
    template<typename T> 
    struct CData<const T> : CData<T> {};


  то есть полностью должно быть так
class CFakeArgument {
    typedef double alignAs_t; // можно прагамами, С++11 или ещё как замутить, не суть.
    enum { bufSize = 32 }; // В общем сколько стеку не жаль
    
    struct CBuffer {
        alignAs_t alignPad;
        char bytes[bufSize - sizeof( alignAs_t )];
    } buffer;

    typedef  void deleter_t( void* );
    deleter_t* deleter;
    void* data;
    
    CFakeArgument( const CFakeArgument& ); // = delete
    void operator = ( const CFakeArgument& ); // = delete
    
    //    Полиморфная часть
    template<typename T> 
    struct CData {
        T Data;
        
        void* operator new( size_t size, CBuffer& dstBuffer )
        {
            if( sizeof( CData ) <= bufSize ) {
                assert( size <= bufSize );
                return &dstBuffer;
            } else {
                return ::new char[size];
            }
        }

        void operator delete( void* p, CBuffer& dstBuffer )
        {
            if( sizeof( CData ) <= bufSize ) {
                assert( p == 0 || p == &dstBuffer );
            } else {
                ::delete[] (char*)p;
            }
        }

        void operator delete( void* p )
        {
            if( sizeof( CData ) > bufSize ) {
                ::delete[] (char*)p;
            }
        }

        static void deleter( void* p )
        {
            delete static_cast<CData*>( p );
        }
        
        T& Save( void*& thisStorage, deleter_t*& deleterStorage )
        {
            assert( thisStorage == 0 && deleterStorage == 0 );
            thisStorage = this;
            deleterStorage = deleter;
            return Data;
        }
    };
    
    template<typename T> 
    struct CData<const T> : CData<T> {};


public:
    CFakeArgument() : deleter( 0 ), data( 0 ) {}; // По просьбам трудящихся ;)
    ~CFakeArgument() { if(deleter != 0 ) deleter( data ); }
    
    template<typename T>
    operator T&()
    {
        if( data == 0 ) {
            return ( new( buffer ) CData<T> )-> Save( data, deleter );
        } else {
            assert( deleter == CData<T>::deleter );
            return static_cast<CData<T>*>(data)->Data;
        }
    }
    template<typename T>
    operator T*() { return &(T&)(*this); }
};

#define _0_ CFakeArgument()

Прада, если делать это всё законченным решением, то нехило бы поддержать ещё и буфера.
Например, можно приписать operator[], которому в аргумент передаёют размер буфера, а он возвращает аналог или наследник CFakeArgument, который по operator T*() аллокирует буфер нужного размера. Правда всё раво не ясно, что делать с T**, которые обычно используются для того, что бы передать указатель на буфер, который будет аллокирован внутри функции и возвращён наружу, так как есть, как минимум два популярных способа его разрушения. Через free и через delete[]...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Как избавиться от лишних аргументов
От: Sni4ok  
Дата: 28.09.12 12:44
Оценка:
Здравствуйте, Константин, Вы писали:

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


чё за бред, по вашему и strlen на 0 проверяет?
Re[3]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 28.09.12 13:41
Оценка:
Здравствуйте, Sni4ok, Вы писали:

S>чё за бред, по вашему и strlen на 0 проверяет?


Я думаю, что имелись в виду факультативные параметры...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 29.09.12 08:38
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


<...>

PMT>Что посоветуете сделать?


http://users.livejournal.com/_winnie/229311.html -- тоже метод
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как избавиться от лишних аргументов
От: DestinyChild  
Дата: 29.09.12 11:10
Оценка:
ндя.... прочитал все и так понял, что не удивительно, что у нас год от года все больше гигарец и гигабайт доступно, но проги все больше и больше тупят и тормозят...
уважаемый PlusMyTwitterFace: писать самое главное надо просто — и если вам что-то не нравиться в чем-то — это не повод изобретать велики и носки-самокаты с нуля. И все уважаемые советчики — нахрена в данной ситуации вы даже просто позволили себе подумать — А КАК эту задачу можно решать по другому? Нахрена городить уйму строк с шаблонами и черт-еще-знает-чем? Просто потому что С++ это позволяет — а вы решили что так можно написать?
Простейшая ситуация, когда надо задать только последний параметр в функции превратилась просто в монстра по решениям. Вам не страшно потом этот ужас поддерживать? Исправлять? Передавать, так сказать, по наследству кому-то?
Вот ответьте сперва на главнейший вопрос — нафига в вопросе, заданном PlusMyTwitterFace вообще искать какое-то новое решение?
Кто и главное КАК выиграет от нового решения? и в чем?
Re[3]: Как избавиться от лишних аргументов
От: DestinyChild  
Дата: 29.09.12 13:41
Оценка:
Здравствуйте, Centaur, Вы писали:

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


DC>>нахрена в данной ситуации вы даже просто позволили себе подумать[…]?


C>Потому что можем.


можем что? просто написать кучу кода, который компилируется и не падает?
а нафига? это важный вопрос — а на него походу никто ответа не знает)))
в данном случае ничего не надо делать. просто подать пустые переменные,
да не используются, да, место занимают, но:
1. короче чем 3 доп. строки общей длиной в символов 15 вы так и не дали решения.
тока увеличили раз в 10.
2. понимания с первого прочтения новый "расширенный" код не дает. Тока путает.
Кому от этого в этом случае станет легче? никому.
3. к 100% идентично-верному решению не подошел ни один из участников топика,
что означает, что доподлинно никто не знает верного решения, а решение, которое
вы формируете тут на ходу — все в подводных камнях и проблемах. В то время как
решение с доп.переменными 100% рабочее и верное.

Так нафига блоху подковывать, а?
Re: Как избавиться от лишних аргументов
От: ChromY  
Дата: 29.09.12 15:29
Оценка:
Здравствуйте, PlusMyTwitterFace, Вы писали:

PMT>Можно ли каким-то образом "избавиться" от "лишних" аргументов функции?


1.Для User-defined, часто используемых и требующих громоздкой инициализации,
сделать производные типы, создающие объекты по умолчанию.
2.Разобраться в логике этих функций и сделать адаптеры для сокращения кода.
Больше никаким образом, и это не связано со спецификой языка.
Re[4]: Как избавиться от лишних аргументов
От: freestyle  
Дата: 29.09.12 15:44
Оценка:
Здравствуйте, 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.
Re[2]: Как избавиться от лишних аргументов
От: Erop Россия  
Дата: 29.09.12 19:58
Оценка:
Здравствуйте, DestinyChild, Вы писали:


DC>Вот ответьте сперва на главнейший вопрос — нафига в вопросе, заданном PlusMyTwitterFace вообще искать какое-то новое решение?

Потому, что оно лучше.
Смотри, например, сюда:
http://users.livejournal.com/_winnie/229311.html

DC>Кто и главное КАК выиграет от нового решения? и в чем?

Код станет проще, понятнее, будет лучше поддерживаться и всё такое...

А если тебя смутила задачка, как сделать так, что бы _ сам разрешался в то, в что надо, то это просто прикольный простенький этюд... К собственно задаче ТС прямого отношения не имеет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.