Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
specification.hpp:
#ifndef SPECIFICATION_HPP
# define SPECIFICATION_HPP
# include <ostream>
/**
* @brief Functions input parameter
*/# define IN
/**
* @brief Functions input/output parameter
*/# define IN_OUT
/**
* @brief Functions output parameter
*/# define OUT
# if 1 // in< class Type > - Functions input parameter
/**
* @brief Functions input parameter
* @tparam Type none reference input parameter type
*/template< class Type >
class in
{
public:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type& value ): value_( value ) {}
/**
* Cast operator
* @return input parameter value
*/operator const Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type& operator ()() const
{
return value_;
}
private:
template< class OtherType >
in( const OtherType& value ); // disable implicit conversion for none reference objects
/**
* input parameter value
*/const Type value_;
};
/**
* @brief Functions input parameter
* @tparam Type reference input parameter type
*/template< class Type >
class in< Type& >
{
public:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type& value ): value_( value ) {}
/**
* Cast operator
* @return input parameter value
*/operator const Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type& operator ()() const
{
return value_;
}
private:
/**
* input parameter value
*/const Type& value_;
};
/**
* @brief Functions input parameter
* @tparam Type pointer input parameter type
*/template< class Type >
class in< Type* >
{
public:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type* const value ): value_( value ) {}
/**
* Cast operator
* @return input parameter value
*/operator const Type*() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type* operator ()() const
{
return value_;
}
/**
* Member selection by pointer operator
* @return input parameter value
*/const Type* operator ->() const
{
return value_;
}
private:
/**
* input parameter value
*/const Type* const value_;
};
# endif
# if 1 // in_out< class Type& > - Functions input-output parameter
/**
* @brief Functions input-output parameter
* @tparam Type none pointer input-output parameter type
*/template< class Type >
class in_out
{
public:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type& value ): value_( value ) {}
/**
* Cast operator
* @return input-output parameter value
*/operator Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type& operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/template< class ValueType >
Type& operator =( const ValueType& value )
{
return value_ = value;
}
private:
/**
* input-output parameter value
*/
Type& value_;
};
/**
* @brief Functions input-output parameter
* @tparam Type pointer input-output parameter type
*/template< class Type >
class in_out< Type* >
{
public:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type* & value ): value_( value ) {}
/**
* Cast operator
* @return input-output parameter value
*/operator Type* &() const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type* & operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return input-output parameter value
*/
Type* operator ->() const
{
return value_;
}
private:
/**
* input-output parameter value
*/
Type* & value_;
};
# endif
# if 1 // out< class Type* > - Functions output parameter
/**
* @brief Functions output parameter
* @tparam Type none pointer output parameter type
*/template< class Type >
class out
{
public:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type& value ): value_( value ) {}
/**
* Cast operator
* @return output parameter value
*/operator Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type& operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/template< class ValueType >
Type& operator =( const ValueType& value )
{
return value_ = value;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool used()
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool not_used()
{
return !used();
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out unused()
{
return out( *reinterpret_cast< Type* >( NULL ) );
}
private:
/**
* output parameter value
*/
Type& value_;
};
/**
* @brief Functions output parameter
* @tparam Type pointer output parameter type
*/template< class Type >
class out< Type* >
{
public:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type* & value ): value_( value ) {}
/**
* Cast operator
* @return output parameter value
*/operator Type* &() const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type* & operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return output parameter value
*/
Type* operator ->() const
{
return value_;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool used()
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool not_used()
{
return !used();
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out unused()
{
return out( *reinterpret_cast< Type** >( NULL ) );
}
private:
/**
* output parameter value
*/
Type* & value_;
};
# endif/**
* Ostream output operator
* @param os output stream
* @param output output value
* @return output stream
* @tparam CharType @a os character type
* @tparam OutputType @a output type
*/template< class CharType, class OutputType >
std::basic_ostream< CharType >& operator <<( in_out< std::basic_ostream< CharType > > os, const OutputType& output )
{
return os() << output;
}
#endif/* SPECIFICATION_HPP */
А вот сравнение использования обычного и с применением in, in_out и out параметров:
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — всего 1 год, до этого я писал на Java. Идея ввести IN, IN-OUT и OUT параметры вначале мне тоже не понравилась, и в начале мы хотели ввести параметры просто как define-ы. Но решающим для меня доводом от коллег было то, что новичкам будет легче понять уже существующий код, если ввести такие "подсказки". Я пошел немного дальше и решил возложить проверку параметров также на компилятор.
Да пожалуйста. Вы главное, постарайтесь понять, о чем я вам говорю. Я пишу на C++ 7 лет, профессионально и большие проекты, я тим-лидер и архитектор.
Во-первых, если у вас трудности с пониманием концепции in/out параметров после джавы, где все параметры in, стоит самому подучиться, потренироваться на нормальных примерах, чтобы улучшить свое понимание, а не бросаться переделывать язык.
Во-вторых, вы (и не только вы, а многие) почему-то считают, что язык C++ можно расширять, добавляя свои правила и новые синтаксические конструкции.
На вопрос "позволяет ли язык C++ добавлять новые языковые конструкции?" ответ будет один: НЕТ. Нет, язык C++ не предназначен его создателями для расширения и введения новых правил типа указания входных параметров. То, что вы пытаетесь сделать — это просто уродливый хак. Вот почему-то те, кто пишет на джаве не пытаются делать подобных уродств. Видимо, язык C++ проклят.
В языке C++ НЕТ синтаксиса указания выходных параметров, как в C#. Попытки ввести эту возможность с помощью шаблонных и других конструкций — это просто уродование программы. Надо с этим смириться, так как, уверяю вас, это совершенно незначительная проблема, не приводящая к каким-либо последствиям в проектах любого размера и сложности.
Вы про Doxygen слышали? Пишите нормальные комментарии, а не разводите порнографию, честное слово.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
On 18.09.2011 11:46, Аноним 966 wrote:
> Во-первых, если у вас трудности с пониманием концепции in/out параметров после > джавы, где все параметры in, стоит самому подучиться, потренироваться на > нормальных примерах, чтобы улучшить свое понимание, а не бросаться переделывать > язык.
В Java можно передавать параметры по ссылке (собственно, стандартный способ
передачи объектов) и если ссылка не константная, то её можно менять в
принимающем методе. Это полный аналог IN_OUT.
> На вопрос "позволяет ли язык C++ добавлять новые языковые конструкции?" ответ > будет один: НЕТ. Нет, язык C++ не предназначен его создателями для расширения и > введения новых правил типа указания входных параметров. То, что вы пытаетесь > сделать — это просто уродливый хак. Вот почему-то те, кто пишет на джаве не > пытаются делать подобных уродств. Видимо, язык C++ проклят.
Да почему же уродливый хак ? Нормально всё. Только соотношение целей и
накладухи не выдерживает никакой критики.
Собственно, правильно оформленные сигнатуры методов и фукнций -- всё, что надо
для этого в С++.
> В языке C++ НЕТ синтаксиса указания выходных параметров, как в C#. Попытки
Есть, неконстантная ссылка, указатель на неконстанту.
И есть входных параметров -- константная ссылка либо по значению.
Как-то странно это слышать после ваших 7-ми лет.
Posted via RSDN NNTP Server 2.1 beta
Re: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
Я за такое избил бы коллегу клавиатурой. Это называется "синдром засирания всего кода ради ничтожной цели". Эта болезнь часто поражает начинающих программистов на C++ — неумение оценивать отношение важности задачи и сложности решения, сосредоточенность на второстепенных вещах, а также на коде вместо самой задачи. У меня тоже было что-то подобное.
Эта проблема — указание направления параметра, — не является такой серьезной, чтобы ради нее так изуродовать всю программу, катастрофически увеличить время компиляции, размер исполняемых файлов и превратить отладку в ад (даже в функцию отладчиком нормально будет не зайти).
И в любом случае нет необходимости указывать указывать направление "in" — оно и так понятно "по умолчанию", и в нормально написанных программах встречается в 99,99% случаев.
Re[7]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Вроде написал более рабочий вариант specification.hpp:
Да, уже лучше, только у нас, по прежнему, не поддерживается преобразование unique_ptr<A> -> unique_ptr<const A>, можно, конечно, сделать его явно:
std::unique_ptr< A > p2( new A );
sink2( in< std::unique_ptr< const A > >( std::move( std::unique_ptr< const A >( std::move(p2) ) ) ) );
Но, я надеюсь, никому не придет в голову сказать что этот ужас читать легче чем
std::unique_ptr< A > p1( new A );
sink1( std::move( p1 ) );
Кроме того, у этого подхода есть ещё, скажем так, концептуальная проблема, из-за того что некоторые способы передачи параметров не укладываются в in, in_out и out. Например, мы хотим передавать владение unique_ptr дальше по цепочке вызовов:
void sink( std::unique_ptr< const A > arg)
{
}
void sink1( std::unique_ptr< const A > arg)
{
sink(std::move(arg));
}
После этого можно будет вспомнить о существовании rvalue-references и необходимости поддерживать perfect forwarding.
Re[17]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
KO>>>>>>Попробуйте повторить этот пример используя ваш specification.hpp.
GRF>>>Вроде теперь ваш пример работает
KO>>Зато, теперь не работает добавление константности:
GRF>А для каких целей нужно будет добавление константности если полностью перейти на in, in_out, out нотацию? GRF>Как я понимаю in параметр должен гарантировать толко неизменность передаваемого внешнего для функции параметра.
Многие (я в том числе) предпочитают обеспечивать, также, неизменяемость входных параметров внутри самой функции (см., например, "Совершенный Код" 2-е издание, изд. Питер, с. 173). Вы сами-то здесь
зачем заменили 'int* bar_in' на 'const int* const bar_in'? То, что в некоторых случаях их всё-таки имеет смысл делать изменяемыми, всего лишь, показывает ограниченность модели in/in_out/out (или, если хотите, системы типов C++). В принципе, всё это прекрасно решается введением соглашений об именовании параметров (например, добавлением префиксов in, inOut, out к именам параметров) и code review, но, в этом случае нет никакого смысла и в дополнительных обёртках, таких как ваши.
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
On 09/14/2011 05:16 PM, Galiulin Rishat Faimovich wrote:
> Хочу подробнее описать причину использования именно этой модели, а не > стандартной и не модели с define-ами: > > 1. С помошью стандартной модели можно реализовать все три типа параметров, но > в местах вызова функций непонятно передается параметр по ссылке или по > значению. Также для стандартной модели существует неавное приведение типов. > 2. Для define-ов, так как они являются просто заглушками, характерны все > высше перечисленные недостатки. К ним еще прибавляется > несинхронизированность между вставленными IN, IN_OUT и OUT > "украшательсвами" и реальными характеристиками параметров в результате > частых изменений кода.
Не, мне это всё лично не нравится. Нагорожен огород, а зачем, не понятно.
В С++ и так нужно всё время смотреть, как используются параметры внутри
функции, меняются или нет, либо в коде, либо в спецификации на функцию.
Ничего страшного тут нет.
Я лучше бы предпочёл смотреть куда-то при необходимости, чем писать
такие вот конструктивы.
Вообще, функция и параметры должны называться так, чтобы и так было всё
понятно.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
On 16.09.2011 21:06, Аноним 966 wrote:
> > Я за такое избил бы коллегу клавиатурой. Это называется "синдром засирания всего > кода ради ничтожной цели". Эта болезнь часто поражает начинающих программистов > на C++ — неумение оценивать отношение важности задачи и сложности решения, > сосредоточенность на второстепенных вещах, а также на коде вместо самой задачи. > У меня тоже было что-то подобное.
Ну, в защиту топикстартера хочу сказать, что мы тоже такое делаем. Главное
отличие -- ДЛЯ ЧЕГО.
Мы это делаем для гарантированно правильных выховов хранимых процедур на сервере
БД. Для вызовов генерируются С++-ые классы-proxy, содержащие нужные
функции, и вызовы производятся только через них. При вызове контролируется
тип каждого параметра, имя параметра, и что он помечен как входной, или
входной и выходной.
Но прикол тут как раз в том, что кравивость и удобнойть такого вызова нам
НЕ НУЖНА -- эти вызовы и с, и без этого некрасивы, громоздки и уродливы
(ну нет передачи в С++ параметров по имени, ну что ж поделать).
Поэтому такие шаблоны вызовов очень полезны.
Но вставлять это ВО ВСЕХ МЕСТАХ -- это безумие.
Лучше переработать дизайн, чтобы все параметры были входными, а возврат
шёл только через значение. Тут это можно сделать, в отличие от вызовов
БД, там надо экономить round trip-ы.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, rumit7, Вы писали:
R>Прикольно, значит по Вашему у человека, который сумел реализовать всю эту шаблонную магию не достаточно практики с указателями/ссылками? Вы вообще как себе это представляете? Вы понимаете, что человек который не понимает как работают указатели/ссылки не пойдет дальше и не начнет реализовывать дополнительные средства?
Да никакая это не магия. Это детский сад. Я в первые один-два года на C++ тоже ваял шаблонные кошмары а ля Александреску (я тогда и не знал, кто это такой), потому что прикольно это было. Половину буста переизобрел, не догадываясь о его существовании. Тех, кому приходилось сопровождать мои первые проекты, мне искренне жаль.
Ну, во-первых, г-н Александреску — это, хоть и умный мужик и ценный кадр, но известный порнограф, вклад которого в создание шаблонных порнобиблиотек трудно переоценить.
Во-вторых, что-то из подобных трудов я и сам использую, придерживаясь правила "все хорошо в меру" и, опять же, KISS и бритвы Оккама.
В-третьих, вы понимаете разницу между синтаксической конструкцией, поддерживаемой компилятором, и самопальной пародией на такую конструкцию из говна и палок. Например, лямбды в C++ 11 и Boost.Lambda. Разницу надо объяснять? Язык, в котором поддерживается расширение синтаксиса — это, например, любимый на этом форуме Немерле. Вот там — совсем другое дело, потому что язык специально для этих целей и делался.
Ну и, наконец, пример топикстартера — это случай, когда определенно цель не стоит средств, он ни в какие ворота не лезет.
А>>На вопрос "позволяет ли язык C++ добавлять новые языковые конструкции?" ответ будет один: НЕТ. Нет, язык C++ не предназначен его создателями для расширения и введения новых правил типа указания входных параметров. То, что вы пытаетесь сделать — это просто уродливый хак. Вот почему-то те, кто пишет на джаве не пытаются делать подобных уродств. Видимо, язык C++ проклят.
R>А мужики то не знают!
Мне жаль этих мужиков. Кругозор надо расширять.
Re[18]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
KO>>>>>>>Попробуйте повторить этот пример используя ваш specification.hpp.
GRF>>>>Вроде теперь ваш пример работает
KO>>>Зато, теперь не работает добавление константности:
GRF>>А для каких целей нужно будет добавление константности если полностью перейти на in, in_out, out нотацию? GRF>>Как я понимаю in параметр должен гарантировать толко неизменность передаваемого внешнего для функции параметра.
KO>Многие (я в том числе) предпочитают обеспечивать, также, неизменяемость входных параметров внутри самой функции (см., например, "Совершенный Код" 2-е издание, изд. Питер, с. 173). Вы сами-то здесь
зачем заменили 'int* bar_in' на 'const int* const bar_in'? То, что в некоторых случаях их всё-таки имеет смысл делать изменяемыми, всего лишь, показывает ограниченность модели in/in_out/out (или, если хотите, системы типов C++). В принципе, всё это прекрасно решается введением соглашений об именовании параметров (например, добавлением префиксов in, inOut, out к именам параметров) и code review, но, в этом случае нет никакого смысла и в дополнительных обёртках, таких как ваши.
, убедили и меня и коллег полностью отказаться от введения как IN, IN-OUT и OUT define-ов (они не контролируются компилятором и следовательно могут ввести в заблуждение), так и in, in_out и out шаблонов (они вводят сильные ограничения) и перейти на стандартную модель.
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку.
я вам могу порекомендовать отказаться от out\inout параметров и тогда ваши проблемы исчезнут сами собой
Re: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
GRF>
On 13.09.2011 18:41, Galiulin Rishat Faimovich wrote:
> Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но > в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные > ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы > их раработать самим. В результате получилась такая реализация, но мы в ней не
А какой цели вы пытались достигнуть ?
Что в результате стало лучше в коде с использованием ваших IN, IN-OUT и OUT ?
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 13.09.2011 18:41, Galiulin Rishat Faimovich wrote:
>> Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но >> в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные >> ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы >> их раработать самим. В результате получилась такая реализация, но мы в ней не
MZ>А какой цели вы пытались достигнуть ? MZ>Что в результате стало лучше в коде с использованием ваших IN, IN-OUT и OUT ?
Спасибо за заинтересованность.
Хотели добиться повышения читабельности кода как для разработчика функции так и для пользователя.
А так же как следствие уменьшение количества ошибок.
В результате вместо ожидаемого малого overhead получили даже некоторую оптимизацию на компиляторах
icc и gcc, на cl к сожалению этот overhead появился (мы сравнивали сгенерированные ассемблерные
инструкции для release версий тестов)
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 13.09.2011 18:41, Galiulin Rishat Faimovich wrote: >> IN, IN-OUT и OUT
MZ>IN есть, MZ>IN-OUT есть, MZ>OUT нет
Я не совсем понял, что ви имели ввиду. Можете написать подробнее?
Re: Реализация IN, IN-OUT и OUT параметров функций
A>Типы параметров нужно указывать при вызове функций? Выглядит очень некрасиво, и писать гораздо больше без особой причины.
A>У меня было так, когда я хотел такое изобрести (но потом выбросил за ненадобностью):
A>
A>string_to_int(in|str, out|n);
A>
Спасибо за пост.
Да согласен что писать надо больше и что выглядит не совсем так хотелось бы. Но есть и плюсы — код читабельнее.
А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку.
Второй плюс — это то улучшает оптимизацию кода на icc и на gcc, к сожалению есть небольшой overhead на cl
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку. U>я вам могу порекомендовать отказаться от out\inout параметров и тогда ваши проблемы исчезнут сами собой
Цитата из "Совершенный код" С.Макконнелла:
"В данном примере ключевые слова-макросы IN и OUT используются для документирования. Чтобы значение параметра можно было изменить в вызванном методе, параметр все же нужно передавать по указателю или по ссылке.
Прежде чем принять этот подход, обдумайте два его важных недостатка. Собственные ключевые слова IN и OUT окажутся незнакомыми большинству программистов, которые будут читать ваш код. Расширяя язык таким образом, делайте это согласованно, лучше всего в масштабе всего проекта. Второй недостаток в том,
что компилятор не будет проверять соответствие параметров ключевым словам IN и OUT, из-за чего вы сможете отметить параметр как IN и все же изменить его внутри метода. Так вы только введете программиста, читающего ваш код, в заблуждение."
На мой взгляд именно эта цитата хорошо отражает намерения автора, а именно:
1) для улучшения читабельности кода;
2) чтобы дать дополнительные гарантии изменяемости/не изменяемости OUT/IN параметров соответственно.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку. U>я вам могу порекомендовать отказаться от out\inout параметров и тогда ваши проблемы исчезнут сами собой
Спасибо за совет.
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
On 13.09.2011 21:17, Galiulin Rishat Faimovich wrote:
> Хотели добиться повышения читабельности кода как для разработчика функции так и > для пользователя.
Для этого достаточно тупо писать комментарии или пустые макросы IN, IN_OUT и OUT
перед параметрами. Для примера см. реализацию современного WinAPI.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
On 13.09.2011 21:20, Galiulin Rishat Faimovich wrote:
> MZ>IN есть, > MZ>IN-OUT есть, > MZ>OUT нет > > Я не совсем понял, что ви имели ввиду. Можете написать подробнее?
Что языком поддерживаются эти парадигмы передачи параметров.
(одна не поддерживается, ещё не поддерживается передача по имени)
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
On 13.09.2011 21:17, Galiulin Rishat Faimovich wrote:
> В результате вместо ожидаемого малого overhead получили даже некоторую > оптимизацию на компиляторах
При передаче болших структур по значению ? Раньше вы по значению
передавали, теперь по константной ссылке ?
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
От:
Аноним
Дата:
14.09.11 09:33
Оценка:
Здравствуйте, MasterZiv, Вы писали:
MZ>On 13.09.2011 21:17, Galiulin Rishat Faimovich wrote:
>> В результате вместо ожидаемого малого overhead получили даже некоторую >> оптимизацию на компиляторах
MZ>При передаче болших структур по значению ? Раньше вы по значению MZ>передавали, теперь по константной ссылке ?
Нет не при передаче больших структур а именно при передаче по ссылке или указателю.
Думаю шаблоны дают компилятору какую-то дополнительную информацию о типе и по этой пирине он убирает излишние проверки.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
От:
Аноним
Дата:
14.09.11 09:45
Оценка:
Здравствуйте, MasterZiv, Вы писали:
MZ>On 13.09.2011 21:17, Galiulin Rishat Faimovich wrote:
>> Хотели добиться повышения читабельности кода как для разработчика функции так и >> для пользователя.
MZ>Для этого достаточно тупо писать комментарии или пустые макросы IN, IN_OUT и OUT MZ>перед параметрами. Для примера см. реализацию современного WinAPI.
Как вы можете заметить у нас так же имеются эти define-ы и мы их использовали.
Проблема была в том что можно было по ошибке написать не то определене перед параметром и
компилятор при этом не выдавал сообщений об ошибке. Шаблонная же реализация обеспечивает жесткую
связь как между определением параметра и его ипользованием, так и между определением функции и ее вызовом.
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
GRF>>
А>И вот это по вашему легче читаемо? А>Не, ну этож песец на ровном месте такие огороды городить.
Да, я думаю, что это достаточно читабельно. Даже без "поскипано"го кода примерно понятно что функция может сделать с параметрами.
Как плюс здесь еще производится проверка типов параметров.
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
От:
Аноним
Дата:
14.09.11 10:47
Оценка:
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Да, я думаю, что это достаточно читабельно. Даже без "поскипано"го кода примерно понятно что функция может сделать с параметрами.
Вы это серьёзно?
Ок, а если будет так:
void foo(IN int* bar_in, OUT char* bar_out, IN_OUT int* bar_in_out);
Разве читающему не будет понятен этот код?
Или он менее читаем чем приведённый вами?
GRF>Как плюс здесь еще производится проверка типов параметров.
Ага, только не как плюс...
Такое ощущение что ради этого всё и затевалось.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Да, я думаю, что это достаточно читабельно. Даже без "поскипано"го кода примерно понятно что функция может сделать с параметрами.
А>Вы это серьёзно? А>Ок, а если будет так:
А>
А>Разве читающему не будет понятен этот код? А>Или он менее читаем чем приведённый вами?
GRF>>Как плюс здесь еще производится проверка типов параметров. А>Ага, только не как плюс... А>Такое ощущение что ради этого всё и затевалось.
Да вы правы иради этого тоже, я просто неправильно выразился
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Да, я думаю, что это достаточно читабельно. Даже без "поскипано"го кода примерно понятно что функция может сделать с параметрами.
А>Вы это серьёзно? А>Ок, а если будет так:
А>
А>Разве читающему не будет понятен этот код? А>Или он менее читаем чем приведённый вами?
GRF>>Как плюс здесь еще производится проверка типов параметров. А>Ага, только не как плюс... А>Такое ощущение что ради этого всё и затевалось.
Хочу подробнее описать причину использования именно этой модели, а не стандартной и не модели с define-ами: С помошью стандартной модели можно реализовать все три типа параметров, но в местах вызова функций непонятно передается параметр по ссылке или по значению. Также для стандартной модели существует неавное приведение типов.
Для define-ов, так как они являются просто заглушками, характерны все высше перечисленные недостатки. К ним еще прибавляется несинхронизированность между вставленными IN, IN_OUT и OUT "украшательсвами" и реальными характеристиками параметров в результате частых изменений кода.
На синтетических тестах модель вроде бы работает. Мы бы очень хотели узнать узкие места такой реализации.
Re[5]: Реализация IN, IN-OUT и OUT параметров функций
On 09/14/2011 01:33 PM, Аноним 20 wrote:
> Нет не при передаче больших структур а именно при передаче по ссылке или указателю. > Думаю шаблоны дают компилятору какую-то дополнительную информацию о типе и по > этой пирине он убирает излишние проверки.
Ну это не очень похоже на правду.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 09/14/2011 05:16 PM, Galiulin Rishat Faimovich wrote:
>> Хочу подробнее описать причину использования именно этой модели, а не >> стандартной и не модели с define-ами: >> >> 1. С помошью стандартной модели можно реализовать все три типа параметров, но >> в местах вызова функций непонятно передается параметр по ссылке или по >> значению. Также для стандартной модели существует неавное приведение типов. >> 2. Для define-ов, так как они являются просто заглушками, характерны все >> высше перечисленные недостатки. К ним еще прибавляется >> несинхронизированность между вставленными IN, IN_OUT и OUT >> "украшательсвами" и реальными характеристиками параметров в результате >> частых изменений кода.
MZ>Не, мне это всё лично не нравится. Нагорожен огород, а зачем, не понятно. MZ>В С++ и так нужно всё время смотреть, как используются параметры внутри MZ>функции, меняются или нет, либо в коде, либо в спецификации на функцию. MZ>Ничего страшного тут нет. MZ>Я лучше бы предпочёл смотреть куда-то при необходимости, чем писать MZ>такие вот конструктивы.
MZ>Вообще, функция и параметры должны называться так, чтобы и так было всё MZ>понятно.
Спасибо за ваше мнение.
Re: Реализация IN, IN-OUT и OUT параметров функций
Я конечно извиняюсь и может чего-то недопонимаю, но с каких это пор код с шаблонами стал читабельнее?
Да и просто сравните длину в символах обычного написания и вашей разработки.
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, DarkTranquillity, Вы писали:
DT>Здравствуйте, Galiulin Rishat Faimovich.
DT>Я конечно извиняюсь и может чего-то недопонимаю, но с каких это пор код с шаблонами стал читабельнее? DT>Да и просто сравните длину в символах обычного написания и вашей разработки.
Да я согласен что длина написания немного увеличилась. Но все же как мне кажется читать код стало легче.
Повторю с пример, который я уже написал:
int main( int argc, char **argv )
{
int Integer = argc;
short InShort = Integer * 2;
int InOutInteger = InShort * 3;
std::string InString( "std::string" );
std::string* pInOutString = &InString;
int* pInOutInteger = &InOutInteger;
Base b;
Derived d;
с параметром читающему код необходимо посмотреть объявление функции.
Теперь посмотрите на эти вызовы:
function_0( in< Base& >( b ) );
или
function_0( in< Base& >( d ) );
Здесь даже без просмотра объявления функции ясно что параметр не будет изменен функцией, а так же что он будет передан по ссылке (не произойдет срезка).
Re: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
Мы поступили по-другому. Параметр может быть либо переменной, либо константой — по аналогии с объявлением переменных и констант в программе.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
LVV>Мы поступили по-другому. Параметр может быть либо переменной, либо константой — по аналогии с объявлением переменных и констант в программе.
Покажите, пожалуйста, примеры используя вашу нотацию.
Re: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
Бессмысленный и беспощадный overdesign, который, к тому же, не всегда работает:
class A
{
};
void sink1(std::unique_ptr<const A> arg)
{
}
void sink2(in<std::unique_ptr<const A>> arg)
{
}
int main()
{
std::unique_ptr<A> p1(new A);
sink1(std::move(p1)); // ok
std::unique_ptr<A> p2(new A);
sink2(in<std::unique_ptr<const A>>(std::move(p2))); // error
}
и не всегда применим:
MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
MyType z = a + b * c;
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
KO>Бессмысленный и беспощадный overdesign, который, к тому же, не всегда работает:
KO>
В нашей нотации необходимо несколько изменить вызов и определение:
class A
{
};
void sink1( const std::unique_ptr< const A > arg)
{
}
void sink2( in< std::unique_ptr< const A >& > arg)
{
}
int main( int argc, char **argv )
{
std::unique_ptr< A > p1( new A );
sink1( std::move( p1 ) ); // ok
std::unique_ptr< A > p2( new A );
sink2( in< std::unique_ptr< const A >& >( std::move( p2 ) ) ); // okreturn 0;
}
KO>и не всегда применим:
KO>
KO>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>
KO>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
KO>
KO>MyType z = a + b * c;
KO>
Мы и не планировали что in, in_out и out будут так применяться .
Посмотрите, пожалуйста, примеры использования в самом первом сообщении .
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, DarkTranquillity, Вы писали:
DT>>Здравствуйте, Galiulin Rishat Faimovich.
DT>>Я конечно извиняюсь и может чего-то недопонимаю, но с каких это пор код с шаблонами стал читабельнее? DT>>Да и просто сравните длину в символах обычного написания и вашей разработки.
GRF>Да я согласен что длина написания немного увеличилась. Но все же как мне кажется читать код стало легче. GRF>Для того чтобы понять что примерно делает GRF>
GRF>function_0( b );
GRF>
GRF>или GRF>
GRF>function_0( d );
GRF>
GRF>с параметром читающему код необходимо посмотреть объявление функции.
GRF>Теперь посмотрите на эти вызовы: GRF>
GRF>function_0( in< Base& >( b ) );
GRF>
GRF>или GRF>
GRF>function_0( in< Base& >( d ) );
GRF>
GRF>Здесь даже без просмотра объявления функции ясно что параметр не будет изменен функцией, а так же что он будет передан по ссылке (не произойдет срезка).
Хм.. а я думал, что еще лучше прикидывать, что делает функция, исходя из ее названия(грамотного, естессно).
По типу параметра, честно, даже в голову не приходило.
Что делает функция f(<in> x) или f(<out> x)?
Еще раз повторюсь, а ниже коллега это подмечает — для Вас шаблоны выглядят читабельнее обычного кода?
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, DarkTranquillity, Вы писали:
DT>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, DarkTranquillity, Вы писали:
DT>>>Здравствуйте, Galiulin Rishat Faimovich.
DT>>>Я конечно извиняюсь и может чего-то недопонимаю, но с каких это пор код с шаблонами стал читабельнее? DT>>>Да и просто сравните длину в символах обычного написания и вашей разработки.
GRF>>Да я согласен что длина написания немного увеличилась. Но все же как мне кажется читать код стало легче. GRF>>Для того чтобы понять что примерно делает GRF>>
GRF>>function_0( b );
GRF>>
GRF>>или GRF>>
GRF>>function_0( d );
GRF>>
GRF>>с параметром читающему код необходимо посмотреть объявление функции.
GRF>>Теперь посмотрите на эти вызовы: GRF>>
GRF>>function_0( in< Base& >( b ) );
GRF>>
GRF>>или GRF>>
GRF>>function_0( in< Base& >( d ) );
GRF>>
GRF>>Здесь даже без просмотра объявления функции ясно что параметр не будет изменен функцией, а так же что он будет передан по ссылке (не произойдет срезка).
DT>Хм.. а я думал, что еще лучше прикидывать, что делает функция, исходя из ее названия(грамотного, естессно). DT>По типу параметра, честно, даже в голову не приходило. DT>Что делает функция f(<in> x) или f(<out> x)? DT>Еще раз повторюсь, а ниже коллега это подмечает — для Вас шаблоны выглядят читабельнее обычного кода?
Иногда да , например: xxx_cast< T >, to< T >
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
KO>>Бессмысленный и беспощадный overdesign, который, к тому же, не всегда работает:
KO>>
GRF>В нашей нотации необходимо несколько изменить вызов и определение:
И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
KO>>и не всегда применим:
KO>>
KO>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>
KO>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
KO>>
KO>>MyType z = a + b * c;
KO>>
GRF>Мы и не планировали что in, in_out и out будут так применяться .
А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
Re[2]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
А>Я за такое избил бы коллегу клавиатурой. Это называется "синдром засирания всего кода ради ничтожной цели". Эта болезнь часто поражает начинающих программистов на C++ — неумение оценивать отношение важности задачи и сложности решения, сосредоточенность на второстепенных вещах, а также на коде вместо самой задачи. У меня тоже было что-то подобное.
А>Эта проблема — указание направления параметра, — не является такой серьезной, чтобы ради нее так изуродовать всю программу, катастрофически увеличить время компиляции, размер исполняемых файлов и превратить отладку в ад (даже в функцию отладчиком нормально будет не зайти).
А>И в любом случае нет необходимости указывать указывать направление "in" — оно и так понятно "по умолчанию", и в нормально написанных программах встречается в 99,99% случаев.
Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — всего 1 год, до этого я писал на Java. Идея ввести IN, IN-OUT и OUT параметры вначале мне тоже не понравилась, и в начале мы хотели ввести параметры просто как define-ы. Но решающим для меня доводом от коллег было то, что новичкам будет легче понять уже существующий код, если ввести такие "подсказки". Я пошел немного дальше и решил возложить проверку параметров также на компилятор.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>Во многих языках есть поддержка со стороны языка IN, IN-OUT и OUT параметров, но в С++ такой нет вместо этого приходиться ипользовать константные и неконстантные ссылки и/или указатели. Поэтому я со своими коллегами решили что лучше было бы их раработать самим. В результате получилась такая реализация, но мы в ней не совсем уверены и хотели бы узнать мнение сообщества:
KO>>>Бессмысленный и беспощадный overdesign, который, к тому же, не всегда работает:
KO>>>
GRF>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
Нет вы получите именно то поведение которое желаете, попробуйте.
KO>>>и не всегда применим:
KO>>>
KO>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>
KO>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
KO>>>
KO>>>MyType z = a + b * c;
KO>>>
GRF>>Мы и не планировали что in, in_out и out будут так применяться .
KO>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
Например в определении функции так:
void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
{
MyType z = a() + b() * c();
}
Для того чтобы писать:
MyType z = a + b * c;
надо будет перегрузить операторы.
Re[5]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
GRF>Нет вы получите именно то поведение которое желаете, попробуйте.
Но позвольте, конструкторы класса 'in' принимают константную ссылку на значение аргумента, мне же нужно передавать аргумент по-значению, для unique_ptr передача по константной ссылке и передача по значению это две большие разницы. Впрочем, я попробовал, как и ожидалось, "эквивалентный" код успешно компилируется, там где оригинальный (как и задумывалось) приводит к ошибке компиляции.
KO>>>>и не всегда применим:
KO>>>>
KO>>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>>
KO>>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
GRF>>>Мы и не планировали что in, in_out и out будут так применяться .
KO>>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
GRF>Например в определении функции так: GRF>
GRF>void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
GRF>{
GRF> MyType z = a() + b() * c();
GRF>}
GRF>
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>>>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
GRF>>Нет вы получите именно то поведение которое желаете, попробуйте.
KO>Но позвольте, конструкторы класса 'in' принимают константную ссылку на значение аргумента, мне же нужно передавать аргумент по-значению, для unique_ptr передача по константной ссылке и передача по значению это две большие разницы. Впрочем, я попробовал, как и ожидалось, "эквивалентный" код успешно компилируется, там где оригинальный (как и задумывалось) приводит к ошибке компиляции.
KO>>>>>и не всегда применим:
KO>>>>>
KO>>>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>>>
KO>>>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
GRF>>>>Мы и не планировали что in, in_out и out будут так применяться .
KO>>>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
GRF>>Например в определении функции так: GRF>>
GRF>>void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
GRF>>{
GRF>> MyType z = a() + b() * c();
GRF>>}
GRF>>
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>>>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
GRF>>Нет вы получите именно то поведение которое желаете, попробуйте.
KO>Но позвольте, конструкторы класса 'in' принимают константную ссылку на значение аргумента, мне же нужно передавать аргумент по-значению, для unique_ptr передача по константной ссылке и передача по значению это две большие разницы. Впрочем, я попробовал, как и ожидалось, "эквивалентный" код успешно компилируется, там где оригинальный (как и задумывалось) приводит к ошибке компиляции.
KO>>>>>и не всегда применим:
KO>>>>>
KO>>>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>>>
KO>>>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
GRF>>>>Мы и не планировали что in, in_out и out будут так применяться .
KO>>>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
GRF>>Например в определении функции так: GRF>>
GRF>>void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
GRF>>{
GRF>> MyType z = a() + b() * c();
GRF>>}
GRF>>
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Да согласен что писать надо больше и что выглядит не совсем так хотелось бы. Но есть и плюсы — код читабельнее.
Обоснуй свою точку зрения. Каким образом указывание типов параметров при вызове функции делает код читабельнее? Загромождаете код лишней информацией. Посмотри на свои вызовы функций. Через них же невозможно продраться.
GRF>А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку.
Ты просто хочешь выдать желаемое за действительное.
GRF>Второй плюс — это то улучшает оптимизацию кода на icc и на gcc, к сожалению есть небольшой overhead на cl
Необоснованное заявление. С какой стати это может привести к более оптимизированному коду?
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Да согласен что писать надо больше и что выглядит не совсем так хотелось бы. Но есть и плюсы — код читабельнее.
A>Обоснуй свою точку зрения. Каким образом указывание типов параметров при вызове функции делает код читабельнее? Загромождаете код лишней информацией. Посмотри на свои вызовы функций. Через них же невозможно продраться.
Вы считаете что на момент вызова типы параметров лучше опустить? Мне с коллегами надо об этом подумать еще раз. Пока мы пришли к тому что типы парамтров покажут места приведения типов.
GRF>>А это в свою очередь как я с коллегами ожидаем уменьшит количество ошибок и облегчит дальнейшую поддержку.
A>Ты просто хочешь выдать желаемое за действительное.
Почему же? Ведь многие вводят IN, IN-OUT и OUT define-ы мы просто хотели избавиться от недостатков такого метода. Можете подробнее объяснить, почему вы с этим не согласны? Нам очень нужно ваше мнение.
GRF>>Второй плюс — это то улучшает оптимизацию кода на icc и на gcc, к сожалению есть небольшой overhead на cl
A>Необоснованное заявление. С какой стати это может привести к более оптимизированному коду?
Факт оптимизации мы увидели просматривая ассемблерные листинги как самих функций так и мест их вызова (компилиловать надо с опцией оптимизации иначе как минимум будут вставлены вызовы конструкторов и деструкторов).
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Да согласен что писать надо больше и что выглядит не совсем так хотелось бы. Но есть и плюсы — код читабельнее.
A>Обоснуй свою точку зрения. Каким образом указывание типов параметров при вызове функции делает код читабельнее? Загромождаете код лишней информацией. Посмотри на свои вызовы функций. Через них же невозможно продраться.
Как вы думаете, а такой вид ввызова будет выглядить лучше:
On 16.09.2011 23:10, Galiulin Rishat Faimovich wrote:
> > Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — > всего 1 год, до этого я писал на Java.
Интересно, как же ты эту проблему на Java-то решал.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — всего 1 год, до этого я писал на Java. Идея ввести IN, IN-OUT и OUT параметры вначале мне тоже не понравилась, и в начале мы хотели ввести параметры просто как define-ы. Но решающим для меня доводом от коллег было то, что новичкам будет легче понять уже существующий код, если ввести такие "подсказки". Я пошел немного дальше и решил возложить проверку параметров также на компилятор.
А>Да пожалуйста. Вы главное, постарайтесь понять, о чем я вам говорю. Я пишу на C++ 7 лет, профессионально и большие проекты, я тим-лидер и архитектор.
А>Во-первых, если у вас трудности с пониманием концепции in/out параметров после джавы, где все параметры in, стоит самому подучиться, потренироваться на нормальных примерах, чтобы улучшить свое понимание, а не бросаться переделывать язык.
А>Во-вторых, вы (и не только вы, а многие) почему-то считают, что язык C++ можно расширять, добавляя свои правила и новые синтаксические конструкции.
А>На вопрос "позволяет ли язык C++ добавлять новые языковые конструкции?" ответ будет один: НЕТ. Нет, язык C++ не предназначен его создателями для расширения и введения новых правил типа указания входных параметров. То, что вы пытаетесь сделать — это просто уродливый хак. Вот почему-то те, кто пишет на джаве не пытаются делать подобных уродств. Видимо, язык C++ проклят.
А>В языке C++ НЕТ синтаксиса указания выходных параметров, как в C#. Попытки ввести эту возможность с помощью шаблонных и других конструкций — это просто уродование программы. Надо с этим смириться, так как, уверяю вас, это совершенно незначительная проблема, не приводящая к каким-либо последствиям в проектах любого размера и сложности.
А>Вы про Doxygen слышали? Пишите нормальные комментарии, а не разводите порнографию, честное слово.
Спасибо
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 16.09.2011 23:10, Galiulin Rishat Faimovich wrote:
>> >> Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — >> всего 1 год, до этого я писал на Java.
MZ>Интересно, как же ты эту проблему на Java-то решал.
Никогда не решал такую проблему на Java.
Re[5]: Реализация IN, IN-OUT и OUT параметров функций
От:
Аноним
Дата:
18.09.11 13:37
Оценка:
Здравствуйте, MasterZiv, Вы писали:
>> В языке C++ НЕТ синтаксиса указания выходных параметров, как в C#. Попытки
MZ>Есть, неконстантная ссылка, указатель на неконстанту. MZ>И есть входных параметров -- константная ссылка либо по значению. MZ>Как-то странно это слышать после ваших 7-ми лет.
В C# есть два кейворда — out и ref. В C++ — нет. Понятно, или тебе привести научную работу с обоснованиями и списком ссылок?
Re[3]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 16.09.2011 21:06, Аноним 966 wrote:
>> >> Я за такое избил бы коллегу клавиатурой. Это называется "синдром засирания всего >> кода ради ничтожной цели". Эта болезнь часто поражает начинающих программистов >> на C++ — неумение оценивать отношение важности задачи и сложности решения, >> сосредоточенность на второстепенных вещах, а также на коде вместо самой задачи. >> У меня тоже было что-то подобное.
MZ>Ну, в защиту топикстартера хочу сказать, что мы тоже такое делаем. Главное MZ>отличие -- ДЛЯ ЧЕГО.
MZ>Мы это делаем для гарантированно правильных выховов хранимых процедур на сервере MZ>БД. Для вызовов генерируются С++-ые классы-proxy, содержащие нужные MZ>функции, и вызовы производятся только через них. При вызове контролируется MZ>тип каждого параметра, имя параметра, и что он помечен как входной, или MZ>входной и выходной.
MZ>Но прикол тут как раз в том, что кравивость и удобнойть такого вызова нам MZ>НЕ НУЖНА -- эти вызовы и с, и без этого некрасивы, громоздки и уродливы MZ>(ну нет передачи в С++ параметров по имени, ну что ж поделать).
MZ>Поэтому такие шаблоны вызовов очень полезны.
MZ>Но вставлять это ВО ВСЕХ МЕСТАХ -- это безумие.
MZ>Лучше переработать дизайн, чтобы все параметры были входными, а возврат MZ>шёл только через значение. Тут это можно сделать, в отличие от вызовов MZ>БД, там надо экономить round trip-ы.
Спасибо за ваше мнение. Хотелось бы точнее понять, где стоит использовать эту нотацию, а где не нужно такого делать.
Изложите, пожалуйста, в виде правил.
Re[4]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Да пожалуйста. Вы главное, постарайтесь понять, о чем я вам говорю. Я пишу на C++ 7 лет, профессионально и большие проекты, я тим-лидер и архитектор. А>Во-первых, если у вас трудности с пониманием концепции in/out параметров после джавы, где все параметры in, стоит самому подучиться, потренироваться на нормальных примерах, чтобы улучшить свое понимание, а не бросаться переделывать язык.
Прикольно, значит по Вашему у человека, который сумел реализовать всю эту шаблонную магию не достаточно практики с указателями/ссылками? Вы вообще как себе это представляете? Вы понимаете, что человек который не понимает как работают указатели/ссылки не пойдет дальше и не начнет реализовывать дополнительные средства?
А>Во-вторых, вы (и не только вы, а многие) почему-то считают, что язык C++ можно расширять, добавляя свои правила и новые синтаксические конструкции.
Вы имеете ввиду: 1) "Move Constructors" By Andrei Alexandrescu; 2) "Lambda: unnamed functions in C++" by Jaakko Järvi, Gary Powell;
и многих других?
А>На вопрос "позволяет ли язык C++ добавлять новые языковые конструкции?" ответ будет один: НЕТ. Нет, язык C++ не предназначен его создателями для расширения и введения новых правил типа указания входных параметров. То, что вы пытаетесь сделать — это просто уродливый хак. Вот почему-то те, кто пишет на джаве не пытаются делать подобных уродств. Видимо, язык C++ проклят.
А мужики то не знают!
Re[5]: Реализация IN, IN-OUT и OUT параметров функций
On 09/18/2011 05:18 PM, Galiulin Rishat Faimovich wrote:
>> > Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — >> > всего 1 год, до этого я писал на Java. > > MZ>Интересно, как же ты эту проблему на Java-то решал. > > Никогда не решал такую проблему на Java.
А что ж на плюсах-то припёрло ?
Одинаковые же проблемы.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А> Я в первые один-два года на C++ тоже ваял шаблонные кошмары а ля Александреску (я тогда и не знал, кто это такой), потому что прикольно это было. Половину буста переизобрел, не догадываясь о его существовании.
Самому себе польстить — святое дело!
Re[7]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>>>>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
GRF>>>Нет вы получите именно то поведение которое желаете, попробуйте.
KO>>Но позвольте, конструкторы класса 'in' принимают константную ссылку на значение аргумента, мне же нужно передавать аргумент по-значению, для unique_ptr передача по константной ссылке и передача по значению это две большие разницы. Впрочем, я попробовал, как и ожидалось, "эквивалентный" код успешно компилируется, там где оригинальный (как и задумывалось) приводит к ошибке компиляции.
KO>>>>>>и не всегда применим:
KO>>>>>>
KO>>>>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>>>>
KO>>>>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
GRF>>>>>Мы и не планировали что in, in_out и out будут так применяться .
KO>>>>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
GRF>>>Например в определении функции так: GRF>>>
GRF>>>void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
GRF>>>{
GRF>>> MyType z = a() + b() * c();
GRF>>>}
GRF>>>
KO>>что я делаю не так?
GRF>>>Для того чтобы писать: GRF>>>
GRF>>>MyType z = a + b * c;
GRF>>>
GRF>>>надо будет перегрузить операторы.
KO>>ну да, надо будет, это вы к чему сказали?
GRF>Я имел ввиду что надо будет добавить операторы в specification.hpp .
GRF>Чтобы заработал Ваш пример оператора надо написать так: GRF>
А откуда, при вашем подходе, возьмётся функция 'MyType operator+( const MyType&, const MyType& rhs )'? Если уж быть последовательным, то реализация будет выглядеть как-то так:
MyType operator+( in< MyType& > lhs, in< MyType& > rhs )
{
MyType result(lhs()); // или, если конструктор копии мы тоже запрещаем: MyType result(lhs);
result += rhs; // operator+=(in< MyType &>)return result;
}
В любом случае, мы получаем уже упомянутый ужас:
MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
Или, может, предлагается использовать такой подход не для всех функций? Тогда, пожалуй, стоит перечислить сценарии, в которых предполагается это использовать, в исходном сообщении об этом ничего не было сказано.
Re[8]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Вроде написал более рабочий вариант specification.hpp:
KO>Да, уже лучше, только у нас, по прежнему, не поддерживается преобразование unique_ptr<A> -> unique_ptr<const A>, можно, конечно, сделать его явно:
KO>
KO>std::unique_ptr< A > p2( new A );
KO>sink2( in< std::unique_ptr< const A > >( std::move( std::unique_ptr< const A >( std::move(p2) ) ) ) );
KO>
KO>Но, я надеюсь, никому не придет в голову сказать что этот ужас читать легче чем
KO>
KO>std::unique_ptr< A > p1( new A );
KO>sink1( std::move( p1 ) );
KO>
Да, действительно выглядит плохо . Но можно немного короче
std::unique_ptr< A > p2( new A );
sink2( in< std::unique_ptr< const A > >( std::unique_ptr< const A >( std::move( p2 ) ) ) );
Вот альтернативный вариант specification.hpp:
#ifndef SPECIFICATION_HPP
# define SPECIFICATION_HPP
#include <ostream>
# if 1 // in< class Type > - Functions input parameter
/**
* @brief Functions input parameter
* @tparam Type none reference input parameter type
*/template< class Type >
class in
{
template< class InType > friend in< InType > in_( const InType value );
public:
/**
* Cast operator
* @return input parameter value
*/operator const Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type& operator ()() const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type& value ): value_( value ) {}
template< class OtherType >
in( const OtherType& value ); // disable implicit conversion for none reference objects
/**
* input parameter value
*/const Type& value_;
};
/**
* @brief Functions input parameter
* @tparam Type reference input parameter type
*/template< class Type >
class in< Type& >
{
template< class InType > friend in< InType > in_( const InType value );
public:
/**
* Cast operator
* @return input parameter value
*/operator const Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type& operator ()() const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type& value ): value_( value ) {}
/**
* input parameter value
*/const Type& value_;
};
/**
* @brief Functions input parameter
* @tparam Type pointer input parameter type
*/template< class Type >
class in< Type* >
{
template< class InType > friend in< InType > in_( const InType value );
public:
/**
* Cast operator
* @return input parameter value
*/operator const Type*() const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type* operator ()() const
{
return value_;
}
/**
* Member selection by pointer operator
* @return input parameter value
*/const Type* operator ->() const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type* const value ): value_( value ) {}
/**
* input parameter value
*/const Type* const value_;
};
/**
* Function call input parameter specifier
* @param value input parameter value
* @return input parameter
*/template< class Type >
in< Type > in_( const Type value )
{
return in< Type >( value );
}
/**
* Function call input parameter by reference specifier
* @param value input parameter value
* @return input parameter
*/template< class Type >
in< Type& > in_ref_( const Type& value )
{
return in< Type& >( value );
}
# endif
# if 1 // in_out< class Type& > - Functions input-output parameter
/**
* @brief Functions input-output parameter
* @tparam Type none pointer input-output parameter type
*/template< class Type >
class in_out
{
template< class InOutType > friend in_out< InOutType > in_out_( InOutType& value );
public:
/**
* Cast operator
* @return input-output parameter value
*/operator Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type& operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/template< class ValueType >
Type& operator =( const ValueType& value )
{
return value_ = value;
}
private:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type& value ): value_( value ) {}
/**
* input-output parameter value
*/
Type& value_;
};
/**
* @brief Functions input-output parameter
* @tparam Type pointer input-output parameter type
*/template< class Type >
class in_out< Type* >
{
template< class InOutType > friend in_out< InOutType > in_out_( InOutType& value );
public:
/**
* Cast operator
* @return input-output parameter value
*/operator Type* &() const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type* & operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return input-output parameter value
*/
Type* operator ->() const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type* & value ): value_( value ) {}
/**
* input-output parameter value
*/
Type* & value_;
};
/**
* Function call input-output parameter specifier
* @param value input-output parameter value
* @return input-output parameter
*/template< class Type >
in_out< Type > in_out_( Type& value )
{
return in_out< Type >( value );
}
# endif
# if 1 // out< class Type* > - Functions output parameter
/**
* @brief Functions output parameter
* @tparam Type none pointer output parameter type
*/template< class Type >
class out
{
template< class OutType > friend out< OutType > out_( OutType& value );
public:
/**
* Cast operator
* @return output parameter value
*/operator Type&() const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type& operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/template< class ValueType >
Type& operator =( const ValueType& value )
{
return value_ = value;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool used()
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool not_used()
{
return !used();
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out unused()
{
return out( *reinterpret_cast< Type* >( NULL ) );
}
private:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type& value ): value_( value ) {}
/**
* output parameter value
*/
Type& value_;
};
/**
* @brief Functions output parameter
* @tparam Type pointer output parameter type
*/template< class Type >
class out< Type* >
{
template< class OutType > friend out< OutType > out_( OutType& value );
public:
/**
* Cast operator
* @return output parameter value
*/operator Type* &() const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type* & operator ()() const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return output parameter value
*/
Type* operator ->() const
{
return value_;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool used()
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool not_used()
{
return !used();
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out unused()
{
return out( *reinterpret_cast< Type** >( NULL ) );
}
private:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type* & value ): value_( value ) {}
/**
* output parameter value
*/
Type* & value_;
};
/**
* Function call output parameter specifier
* @param value output parameter value
* @return output parameter
*/template< class Type >
out< Type > out_( Type& value )
{
return out< Type >( value );
}
# endif/**
* Ostream output operator
* @param os output stream
* @param output output value
* @return output stream
* @tparam CharType @a os character type
* @tparam OutputType @a output type
*/template< class CharType, class OutputType >
std::basic_ostream< CharType >& operator <<( in_out< std::basic_ostream< CharType > > os, const OutputType& output )
{
return os() << output;
}
#endif/* SPECIFICATION_HPP */
C ним нужно писать так:
std::unique_ptr< A > p2( new A );
sink2( in_( std::unique_ptr< const A >( std::move( p2 ) ) ) );
KO>Кроме того, у этого подхода есть ещё, скажем так, концептуальная проблема, из-за того что некоторые способы передачи параметров не укладываются в in, in_out и out. Например, мы хотим передавать владение unique_ptr дальше по цепочке вызовов:
KO>
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>>>В нашей нотации необходимо несколько изменить вызов и определение:
KO>>>>>И получить другое поведение? Нет уж, так не пойдёт, боюсь, небольшим изменением тут не отделаться.
GRF>>>>Нет вы получите именно то поведение которое желаете, попробуйте.
KO>>>Но позвольте, конструкторы класса 'in' принимают константную ссылку на значение аргумента, мне же нужно передавать аргумент по-значению, для unique_ptr передача по константной ссылке и передача по значению это две большие разницы. Впрочем, я попробовал, как и ожидалось, "эквивалентный" код успешно компилируется, там где оригинальный (как и задумывалось) приводит к ошибке компиляции.
KO>>>>>>>и не всегда применим:
KO>>>>>>>
KO>>>>>>>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>>>>>>>
KO>>>>>>>во что это превратится с использованием expression templates я даже думать не хочу, впрочем, как я понял, некоторым такой вариант кажется более читабельным по сравнению с
GRF>>>>>>Мы и не планировали что in, in_out и out будут так применяться .
KO>>>>>А как же ещё им применяться? Входные параметры есть, почему их не надо помечать? Впрочем, я, кажется, понимаю: благодаря удачным названиям функций способ использования передаваемых параметров очевиден, может, тогда, вместо изобретения велосипедов, стоит давать более удачные названия функциям?
GRF>>>>Например в определении функции так: GRF>>>>
GRF>>>>void function( in< MyType& > a, in< MyType& > b, in< MyType& > c )
GRF>>>>{
GRF>>>> MyType z = a() + b() * c();
GRF>>>>}
GRF>>>>
KO>>>что я делаю не так?
GRF>>>>Для того чтобы писать: GRF>>>>
GRF>>>>MyType z = a + b * c;
GRF>>>>
GRF>>>>надо будет перегрузить операторы.
KO>>>ну да, надо будет, это вы к чему сказали?
GRF>>Я имел ввиду что надо будет добавить операторы в specification.hpp .
GRF>>Чтобы заработал Ваш пример оператора надо написать так: GRF>>
KO>А откуда, при вашем подходе, возьмётся функция 'MyType operator+( const MyType&, const MyType& rhs )'? Если уж быть последовательным, то реализация будет выглядеть как-то так: KO>
KO>MyType operator+( in< MyType& > lhs, in< MyType& > rhs )
KO>{
KO> MyType result(lhs()); // или, если конструктор копии мы тоже запрещаем: MyType result(lhs);
KO> result += rhs; // operator+=(in< MyType &>)
KO> return result;
KO>}
KO>
KO>В любом случае, мы получаем уже упомянутый ужас: KO>
KO>MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
KO>
Зачем писать:
MyType z = in<MyType&>(in<MyType&>(a) + in<MyType&>(in<MyType&>(b) * in<MyType&>(c)));
когда можно писать:
MyType z = a() + b() * c();
?
KO>Или, может, предлагается использовать такой подход не для всех функций? Тогда, пожалуй, стоит перечислить сценарии, в которых предполагается это использовать, в исходном сообщении об этом ничего не было сказано.
in, in_out и out должны использваться в теле функций или в вызовах функций
Re[6]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, MasterZiv, Вы писали:
MZ>On 09/18/2011 05:18 PM, Galiulin Rishat Faimovich wrote:
>>> > Спасибо за ваше мнение. Я действительно пишу на С++ довольно короткое время — >>> > всего 1 год, до этого я писал на Java. >> >> MZ>Интересно, как же ты эту проблему на Java-то решал. >> >> Никогда не решал такую проблему на Java.
MZ>А что ж на плюсах-то припёрло ? MZ>Одинаковые же проблемы.
Для меня это не явлется проблемой, но большенсво коллег проголосовало за ввод IN, IN_OUT и OUT define-овю.
Как я уже ответил одному из участников, я просто заменил неконтролируемые компилятором define-ы на шаблоны.
Re[9]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>Вроде написал более рабочий вариант specification.hpp:
KO>>Да, уже лучше, только у нас, по прежнему, не поддерживается преобразование unique_ptr<A> -> unique_ptr<const A>, можно, конечно, сделать его явно:
GRF>Да, действительно выглядит плохо . Но можно немного короче
Так ведь можно и ещё короче, если не использовать эти обёртки для параметров.
KO>>Кроме того, у этого подхода есть ещё, скажем так, концептуальная проблема, из-за того что некоторые способы передачи параметров не укладываются в in, in_out и out. Например, мы хотим передавать владение unique_ptr дальше по цепочке вызовов:
KO>>
Понятно, что саму обёртку можно, без проблем, передать дальше.
KO>>После этого можно будет вспомнить о существовании rvalue-references и необходимости поддерживать perfect forwarding.
GRF>При реализации мы к сожалению не ориетировались на новый стандарт С++
Ну это, как бы, заметно, хотя и странно для, подобного рода, инфраструктурного кода.
Re[9]: Реализация IN, IN-OUT и OUT параметров функций
Соответственно, вместо 'operator+(const MyType& lhs, const MyType& rhs)' у нас должен быть 'operator+(in<MyType&> lhs, in<MyType&> rhs)'. Если это не так, возникает вопрос, в чём разница?
KO>>Или, может, предлагается использовать такой подход не для всех функций? Тогда, пожалуй, стоит перечислить сценарии, в которых предполагается это использовать, в исходном сообщении об этом ничего не было сказано.
GRF>in, in_out и out должны использваться в теле функций или в вызовах функций
Вопрос в том, для каких функций параметры должны объявляться с использованием in, in_out и out?
Re[10]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>>>Вроде написал более рабочий вариант specification.hpp:
KO>>>Да, уже лучше, только у нас, по прежнему, не поддерживается преобразование unique_ptr<A> -> unique_ptr<const A>, можно, конечно, сделать его явно:
GRF>>Да, действительно выглядит плохо . Но можно немного короче
KO>Так ведь можно и ещё короче, если не использовать эти обёртки для параметров.
KO>>>Кроме того, у этого подхода есть ещё, скажем так, концептуальная проблема, из-за того что некоторые способы передачи параметров не укладываются в in, in_out и out. Например, мы хотим передавать владение unique_ptr дальше по цепочке вызовов:
KO>>>
KO>Понятно, что саму обёртку можно, без проблем, передать дальше.
KO>>>После этого можно будет вспомнить о существовании rvalue-references и необходимости поддерживать perfect forwarding.
GRF>>При реализации мы к сожалению не ориетировались на новый стандарт С++
KO>Ну это, как бы, заметно, хотя и странно для, подобного рода, инфраструктурного кода.
Для нас сейчас самое важное надежность и переносимость.
Re[11]: Реализация IN, IN-OUT и OUT параметров функций
А самому? Вас же на ideone.com не забанили, надеюсь? В любом случае, результатом arg() будет константная ссылка на unique_ptr<const A>, у которого, разумеется, нет оператора ().
Попробуйте повторить этот пример используя ваш specification.hpp.
Re[12]: Реализация IN, IN-OUT и OUT параметров функций
KO>А самому? Вас же на ideone.com не забанили, надеюсь? В любом случае, результатом arg() будет константная ссылка на unique_ptr<const A>, у которого, разумеется, нет оператора ().
KO>Попробуйте повторить этот пример используя ваш specification.hpp.
Тогда я не понял ваш переидущий ответ KO>>>Кроме того, у этого подхода есть ещё, скажем так, концептуальная проблема, из-за того что некоторые способы передачи параметров не укладываются в in, in_out и out. Например, мы хотим передавать владение unique_ptr дальше по цепочке вызовов:
KO>>>
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Здравствуйте, k.o., Вы писали:
KO>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>Тогда я не понял ваш переидущий ответ
GRF>Зачем тогда здесь скобки у arg ?
Вы меня спрашиваете для чего предназначен 'operator()' у вашего класаа in?
KO>>Попробуйте повторить этот пример используя ваш specification.hpp.
Re[14]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Тогда я не понял ваш переидущий ответ
GRF>>Зачем тогда здесь скобки у arg ?
KO>Вы меня спрашиваете для чего предназначен 'operator()' у вашего класаа in?
KO>>>Попробуйте повторить этот пример используя ваш specification.hpp.
Спасибо, понял проблему. Надо об этом подумать.
Re[7]: Реализация IN, IN-OUT и OUT параметров функций
От:
Аноним
Дата:
19.09.11 17:59
Оценка:
Здравствуйте, alexeiz, Вы писали:
А>> Я в первые один-два года на C++ тоже ваял шаблонные кошмары а ля Александреску (я тогда и не знал, кто это такой), потому что прикольно это было. Половину буста переизобрел, не догадываясь о его существовании.
A>Самому себе польстить — святое дело!
Ну если хочешь, могу еще тебе посочувствовать.
Re[8]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, alexeiz, Вы писали:
А>>> Я в первые один-два года на C++ тоже ваял шаблонные кошмары а ля Александреску (я тогда и не знал, кто это такой), потому что прикольно это было. Половину буста переизобрел, не догадываясь о его существовании.
A>>Самому себе польстить — святое дело!
А>Ну если хочешь, могу еще тебе посочувствовать.
Пожалуйста, не превращайте данный топик в "междоусобчик". Нам очень нужны Ваши советы
Re[14]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Здравствуйте, k.o., Вы писали:
KO>>>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
GRF>>Тогда я не понял ваш переидущий ответ
GRF>>Зачем тогда здесь скобки у arg ?
KO>Вы меня спрашиваете для чего предназначен 'operator()' у вашего класаа in?
KO>>>Попробуйте повторить этот пример используя ваш specification.hpp.
Вот измененный вариант specification.hpp
#ifndef SPECIFICATION_HPP
# define SPECIFICATION_HPP
# include <ostream>
# if 1 // in< class Type > - Functions input parameter
/**
* @brief Functions input parameter
* @tparam Type none reference input parameter type
*/template< class Type >
class in
{
template< class InType >
friend in< InType > in_( const InType value );
public:
/**
* Cast operator
* @return input parameter value
*/operator Type&( ) const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/
Type& operator ( )( ) const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( Type& value ): value_( value ) { }
template< class OtherType >
in( const OtherType& value ); // disable implicit conversion for none reference objects
/**
* input parameter value
*/
Type& value_;
};
template< class Type >
in< Type& > in_ref_( const Type& value );
/**
* @brief Functions input parameter
* @tparam Type reference input parameter type
*/template< class Type >
class in< Type& >
{
template< class InType >
friend in< InType& > in_ref_( const InType& value );
public:
/**
* Cast operator
* @return input parameter value
*/operator const Type&( ) const
{
return value_;
}
/**
* Cast operator
* @return input parameter value
*/template< class BaseType >
operator in< BaseType& >( ) const
{
return in_ref_< BaseType > ( value_ );
}
/**
* Gets parameter value
* @return input parameter value
*/const Type& operator ( )( ) const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type& value ): value_( value ) { }
/**
* input parameter value
*/const Type& value_;
};
/**
* @brief Functions input parameter
* @tparam Type pointer input parameter type
*/template< class Type >
class in< Type* >
{
template< class InType > friend in< InType >
in_( const InType value );
public:
/**
* Cast operator
* @return input parameter value
*/operator const Type*( ) const
{
return value_;
}
/**
* Gets parameter value
* @return input parameter value
*/const Type* operator ( )( ) const
{
return value_;
}
/**
* Member selection by pointer operator
* @return input parameter value
*/const Type* operator ->( ) const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input parameter value
*/explicit in( const Type * const value ): value_( value ) { }
/**
* input parameter value
*/const Type * const value_;
};
/**
* Function call input parameter specifier
* @param value input parameter value
* @return input parameter
*/template< class Type >
in< Type > in_( Type value )
{
return in< Type > ( value );
}
/**
* Function call input parameter by reference specifier
* @param value input parameter value
* @return input parameter
*/template< class Type >
in< Type& > in_ref_( const Type& value )
{
return in< Type& >( value );
}
# endif
# if 1 // in_out< class Type& > - Functions input-output parameter
/**
* @brief Functions input-output parameter
* @tparam Type none pointer input-output parameter type
*/template< class Type >
class in_out
{
template< class InOutType >
friend in_out< InOutType > in_out_( InOutType& value );
public:
/**
* Cast operator
* @return input-output parameter value
*/operator Type&( ) const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type& operator ( )( ) const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/template< class ValueType >
Type& operator =(const ValueType& value )
{
return value_ = value;
}
private:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type& value ): value_( value ) { }
/**
* input-output parameter value
*/
Type& value_;
};
/**
* @brief Functions input-output parameter
* @tparam Type pointer input-output parameter type
*/template< class Type >
class in_out< Type* >
{
template< class InOutType >
friend in_out< InOutType > in_out_( InOutType& value );
public:
/**
* Cast operator
* @return input-output parameter value
*/operator Type* &( ) const
{
return value_;
}
/**
* Gets parameter value
* @return input-output parameter value
*/
Type* & operator ( )( ) const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return input-output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return input-output parameter value
*/
Type* operator ->( ) const
{
return value_;
}
private:
/**
* Initialization constructor
* @param value input-output parameter value
*/explicit in_out( Type* & value ): value_( value ) { }
/**
* input-output parameter value
*/
Type* & value_;
};
/**
* Function call input-output parameter specifier
* @param value input-output parameter value
* @return input-output parameter
*/template< class Type >
in_out< Type >
in_out_( Type& value )
{
return in_out< Type > ( value );
}
# endif
# if 1 // out< class Type* > - Functions output parameter
/**
* @brief Functions output parameter
* @tparam Type none pointer output parameter type
*/template< class Type >
class out
{
template< class OutType >
friend out< OutType > out_( OutType& value );
public:
/**
* Cast operator
* @return output parameter value
*/operator Type&( ) const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type& operator ( )( ) const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/template< class ValueType >
Type& operator =(const ValueType& value )
{
return value_ = value;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool
used( )
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool
not_used( )
{
return !used( );
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out
unused( )
{
return out( *reinterpret_cast<Type*> ( NULL ) );
}
private:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type& value ): value_( value ) { }
/**
* output parameter value
*/
Type& value_;
};
/**
* @brief Functions output parameter
* @tparam Type pointer output parameter type
*/template< class Type >
class out< Type* >
{
template< class OutType >
friend out< OutType > out_( OutType& value );
public:
/**
* Cast operator
* @return output parameter value
*/operator Type* &( ) const
{
return value_;
}
/**
* Gets parameter value
* @return output parameter value
*/
Type* & operator ( )( ) const
{
return value_;
}
/**
* Assignment operator
* @param value assignment value
* @tparam ValueType assignment value type
* @return output parameter value
*/
Type* & operator =( Type* value )
{
return value_ = value;
}
/**
* Member selection by pointer operator
* @return output parameter value
*/
Type* operator ->( ) const
{
return value_;
}
/**
* Checks if parameter is used
* @return <code>true</code> if parameter has been set and <code>false</code> otherwise
*/bool
used( )
{
return ( &value_ ) != NULL;
}
/**
* Checks if parameter is not used
* @return <code>true</code> if parameter has not been set and <code>false</code> otherwise
*/bool
not_used( )
{
return !used( );
}
/**
* Creates unused parameter indicator
* @return unused parameter indicator
*/static out
unused( )
{
return out( *reinterpret_cast<Type**> ( NULL ) );
}
private:
/**
* Initialization constructor
* @param value output parameter value
*/explicit out( Type* & value ): value_( value ) { }
/**
* output parameter value
*/
Type* & value_;
};
/**
* Function call output parameter specifier
* @param value output parameter value
* @return output parameter
*/template< class Type >
out< Type >
out_( Type& value )
{
return out< Type > ( value );
}
# endif/**
* Ostream output operator
* @param os output stream
* @param output output value
* @return output stream
* @tparam CharType @a os character type
* @tparam OutputType @a output type
*/template< class CharType, class OutputType >
std::basic_ostream< CharType >& operator <<( in_out< std::basic_ostream< CharType > > os, const OutputType& output )
{
return os( ) << output;
}
#endif/* SPECIFICATION_HPP */
Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
KO>>>>Попробуйте повторить этот пример используя ваш specification.hpp.
GRF>Вроде теперь ваш пример работает
Зато, теперь не работает добавление константности:
void
sink2( in< const std::unique_ptr< const A > > arg )
{
// would like to get compile error for attempts to modify arg, e.g.:
// arg().release();
}
void
sink1( in< std::unique_ptr< const A > > arg )
{
std::cout << "sink1 owns pointer to A: " << arg( ).get( ) << std::endl;
sink2( in_( std::move( arg() ) ) );
std::cout << "sink1 passed ownership to sink2: " << arg( ).get( ) << std::endl;
}
И, хотя, реализовать это нетрудно:
#include <type_traits>
...
template< class Type >
class in
{
public:
in( const in<typename std::remove_const<Type>::type>& other)
: value_(other())
{
}
...
};
Возникает закономерный вопрос: нафига козе баян зачем нам вся эта шаблонная магия с классом in, если мы теперь всё-равно можем менять передаваемые аргументы, а константность нужно добавлять самому, точно также, как и с обычными параметрами? Собственно, в этом и заключается "концептуальная проблема" вашего подхода: он либо слишком ограничивающий, либо, мало чем отличается (кроме лишней писанины) от обычной передачи параметров.
Re[16]: Реализация IN, IN-OUT и OUT параметров функций
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Galiulin Rishat Faimovich, Вы писали:
KO>>>>>Попробуйте повторить этот пример используя ваш specification.hpp.
GRF>>Вроде теперь ваш пример работает
KO>Зато, теперь не работает добавление константности: KO>
KO>void
KO>sink2( in< const std::unique_ptr< const A > > arg )
KO>{
KO> // would like to get compile error for attempts to modify arg, e.g.:
KO> // arg().release();
KO>}
KO>void
KO>sink1( in< std::unique_ptr< const A > > arg )
KO>{
KO> std::cout << "sink1 owns pointer to A: " << arg( ).get( ) << std::endl;
KO> sink2( in_( std::move( arg() ) ) );
KO> std::cout << "sink1 passed ownership to sink2: " << arg( ).get( ) << std::endl;
KO>}
KO>
А для каких целей нужно будет добавление константности если полностью перейти на in, in_out, out нотацию?
Как я понимаю in параметр должен гарантировать толко неизменность передаваемого внешнего для функции параметра.
Re[19]: Реализация IN, IN-OUT и OUT параметров функций
, убедили и меня и коллег полностью отказаться от введения как IN, IN-OUT и OUT define-ов (они не контролируются компилятором и следовательно могут ввести в заблуждение), так и in, in_out и out шаблонов (они вводят сильные ограничения) и перейти на стандартную модель.
"Стандартную" это какую? Все-таки, в C++ не решены две проблемы:
1) отличения параметров "in-out" от "out" (разница в том, что в первом случае параметр перед вызовом функции должен быть установлен в определенное значение, от которого зависит выполнение функции, а во втором случае значение параметра до вызова функции неважно);
2) запись аргументов "in-out" и "in" при вызове функции при использовании ссылок (C++ way) ничем не отличается от передачи по значению:
void DoSomething(int inParam1, int inParam2, int& inoutParam, int& outParam)
{
}
int main()
{
int a = 0, b = 0, c = 0, d = 0;
DoSomething(a, b, c, d);
return 0;
}
Я считаю, что пустые дефайны типа INOUT и OUT — все-таки более-менее нормальное решение, исключительно для аннотации.
#define INOUT
#define OUT
void DoSomething(int inParam1, int inParam2, INOUT int& inoutParam, OUT int& outParam)
{
}
int main()
{
int a = 0, b = 0, c = 0, d = 0;
DoSomething(a, b, INOUT c, OUT d);
return 0;
}
Или можно ставить какие-нибудь комментарии.
void DoSomething(int inParam1, int inParam2, /*INOUT*/int& inoutParam, /*OUT*/int& outParam)
{
}
int main()
{
int a = 0, b = 0, c = 0, d = 0;
DoSomething(a, b, /*INOUT*/ c, /*OUT*/ d);
return 0;
}
Честно говоря, мне самому оба решения не нравятся. Для меня это вопрос открытый.
Re[20]: Реализация IN, IN-OUT и OUT параметров функций
On 22.09.2011 0:26, Аноним 492 wrote:
> 1) отличения параметров "in-out" от "out" (разница в том, что в первом случае > параметр перед вызовом функции должен быть установлен в определенное значение, > от которого зависит выполнение функции, а во втором случае значение параметра до > вызова функции неважно);
В отсутствии чистого OUT нет ничего страшного. Этого нет в очень многих
системах программирования.
Если IN в IN_OUT игнорируется телом функции, что ОЧЕНЬ легко и всегда
можно сделать, то проблемы вообще нет.
Во-вторых, можно просто сделать два параметра из одного IN_OUT, один
чисто IN, по значению, другой IN_OUT c семантикой только OUT.
В третьих, можно возвращать значения вообще с помощью того, что возвращает
функция. Не всегда это можно сделать, но можно.
> Я считаю, что пустые дефайны типа INOUT и OUT — все-таки более-менее нормальное > решение, исключительно для аннотации.
Они ни от чего не спасают. Если бы это поддерживал язык, -- да, было бы хорошо.
А так -- всё равно всегда надо смотреть на сигнатуру вызываемой функции и проверять.