Re: Непустой выходной параметр - ваша реакция?
От: bazis1 Канада  
Дата: 22.03.17 17:06
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


Если это не архимегакритический путь с точки зрения производительности, то надо сделать глобальную обертку а-ля OutParameter<vector<Something>>, которая сама будет занулять.
Re: Непустой выходной параметр - ваша реакция?
От: alex_public  
Дата: 22.03.17 17:13
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Что скажете?


pair<result_code, vector<Something>> GetSomething();
Re[4]: Непустой выходной параметр - ваша реакция?
От: andyp  
Дата: 22.03.17 19:05
Оценка: :)
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>auto r =  GetSomething< vector<Something>& >(output);
BFE>

BFE>)

Ход в правильном направлении. Но мы не будем полагаться на случайности:

template<class T> 
typename std::enable_if<std::is_reference<T>::value ,result_type>::type GetSomething(T output);
Re: Непустой выходной параметр - ваша реакция?
От: Masterspline  
Дата: 22.03.17 20:19
Оценка: 2 (1)
Я бы предложил сигнатуру фукнции
vector<Something> GetSomething();

или, если нужен еще и код возврата
std::pair<vector<Something>,result_code> GetSomething();

При условии, что каждый раз перед вызовом функции вектор создается заново, накладные расходы будут примерно, как при передаче ссылки на output.

Правда, тут есть одна неприятность, синтаксис
auto [res, error_code] = GetSomething();

поддерживают только gcc7 и последний MSVC (clang, скорее всего тоже, только вышедший или вот вот появится), в отличие от string_view, например, который есть уже везде в std::experimental.
Re: Непустой выходной параметр - ваша реакция?
От: Masterspline  
Дата: 22.03.17 20:29
Оценка: +2
Еще можно сделать две функции:
result_code GetSomething(vector<Something>& output); ///! очистить буфер и положить в него новые значения
result_code AppendSomething(vector<Something>& output); ///! добавить в буфер новые значения (сохранив предыдущие)


Причем GetSomething() может просто сделать clear() и вызвать AppendSomething().
Re[3]: Непустой выходной параметр - ваша реакция?
От: kov_serg Россия  
Дата: 22.03.17 20:46
Оценка:
Здравствуйте, andyp, Вы писали:

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


_>>Точно не в духе. В C++ надо писать так

_>>
_>>template<class T> result_code GetSomething(T output);
_>>


A>Так ты на выходе ничего не получишь кроме result_code. Так что функцию придется переименовать в GetNothing.


А мужики-то не знают.
template<class T> result_code GetSomething(T output) {
...
  while(iterator.getNext(value)) output(value);
...
}
auto rc=GetSomething([](const Something& s) { ... } );

...

C++ описывает синтаксис, но никак не описывает семантику.
Так что из объявления функции никак не следует как ей можно пользоваться.
Например есть две функции void lock() и void unlock() то на вопрос "можно ли их вызывать влежено", "обязательно после lock вызывать unlock или нет" тишина.
Так что и у вас надо просто документировать что будет делать ваша функция.
Re[4]: Непустой выходной параметр - ваша реакция?
От: andyp  
Дата: 22.03.17 21:55
Оценка:
Здравствуйте, kov_serg, Вы писали:

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


_>А мужики-то не знают.

_>
_>template<class T> result_code GetSomething(T output) {
_>...
_>  while(iterator.getNext(value)) output(value);
_>...
_>}
_>auto rc=GetSomething([](const Something& s) { ... } );
_>

_>...

Ну если это в твоем понимании примерно то, что ТС хотел, то ОК.

_>C++ описывает синтаксис, но никак не описывает семантику.


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

_>Так что из объявления функции никак не следует как ей можно пользоваться.

_>Например есть две функции void lock() и void unlock() то на вопрос "можно ли их вызывать влежено", "обязательно после lock вызывать unlock или нет" тишина.
_>Так что и у вас надо просто документировать что будет делать ваша функция.

Это ТС-ова функция, а не наша. Наша функция для начала имени в формате CamelCase иметь не будет .
Re: Непустой выходной параметр - ваша реакция?
От: Serg27  
Дата: 23.03.17 04:43
Оценка: 2 (1) +1
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


B>Что скажете?

Если result_code имеет только два значения, то для этого придуман тип optional. Он давно есть в BOOST и появится в C++17 (cppreference). В VS2017 этот тип есть. Пример из cppreference:
#include <string>
#include <iostream>
#include <optional>
 
// optional can be used as the return type of a factory that may fail
std::optional<std::string> create(bool b) {
    if(b)
        return "Godzilla";
    else
        return {};
}
int main()
{
    std::cout << "create(false) returned "
              << create(false).value_or("empty") << '\n';
    // optional-returning factory functions are usable as conditions of while and if
    if(auto str = create(true)) {
        std::cout << "create(true) returned " << *str << '\n';
    }
}
Re: Непустой выходной параметр - ваша реакция?
От: Went  
Дата: 23.03.17 06:48
Оценка: +2
Здравствуйте, Basil2, Вы писали:

B>1. Всегда очищать (лишнее действие, что не в духе плюсов).

Неужели clear() для потенциально пустого вектора хоть как-то сопоставим по сложности с кодом, который будет потом этот вектор набирать или даже с самим вызовом функции (очевидно, что clear() заинлайнится и оптимизируется в какой-то cmp банальный)? Никто ведь не ожидает нулевого значения от х и у в случае функции
result_type get_xy(int& x, int& y);

чтобы потом вместо "x = 10", написать "x += 10". Так и в вашем случае — get есть get. Поэтому при такой сигнатуре — однозначно очищать.

B>2. Игнорировать, т.е. новые значения добавятся к старым ("не очистил сам дурак" — вполне в духе, но добавляет нестабильности).

Только в случае, если собираетесь явно обозначить это пользователю, назвав "append...". Однако в этом случае почему именно вектор? Тут уже лучше или функцию передавать или через открытый шаблон с итератором.

B>3. Должен сработать assert (типа assert(!output.empty)).

В самом крайнем случае, если это внутренности и очень важна оптимизация. Только, наверное "!" лишний?

B>4. Вернуть ошибку/бросить исключение.

Просто дичь.
Re: Спасибо за ответы (+)
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.03.17 12:02
Оценка: +1
B>Есть функция:
B>
B>result_code GetSomething(vector<Something>& output);
B>

B>При одном из вызовов функции передается непустой вектор. Как, на ваш взгляд, функция должна отреагировать на это?

Пару слов о принятых решениях:

1. Мне тоже нравится сигнатура vector<Something> GetSomething() (она еще и позволяет использовать константы), но по правилам используемой библиотеки все функции должны возвращать result_code.

2. В итоге принято решение "всегда очищать". Почему: потери времени минимальны (вектор ожидается пустым в абсолютном большинстве случаев). При этом возможные геморрои, связанные с отладкой или сложными названиями, полностью исключаются.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re: Непустой выходной параметр - ваша реакция?
От: AlexGin Беларусь  
Дата: 24.03.17 09:28
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


B>При одном из вызовов функции передается непустой вектор. Как, на ваш взгляд, функция должна отреагировать на это?


B>1. Всегда очищать (лишнее действие, что не в духе плюсов).

B>2. Игнорировать, т.е. новые значения добавятся к старым ("не очистил сам дурак" — вполне в духе, но добавляет нестабильности).
B>3. Должен сработать assert (типа assert(output.empty)).
B>4. Вернуть ошибку/бросить исключение.
B>5. Оставлю комментарий со своим вариантом.

B>(Хотел сделать настоящее голосование, но получаю "500 — Internal server error". Зато здесь можно обсудить более развернуто).


B>Что скажете?


ИМХО всё зависит от условий задачи/проекта.
Так, если мы только заполняем получаемыми значениями, то можно первоначально дать очистку вектора.
Если же GetSomething может что-то добавлять — то очистку делать не следует,
тогда логичнее назвать этот метод/функцию: Add... или Append...

Остальные варианты — представляются мне не актуальными для данного случая.
Отредактировано 24.03.2017 9:31 AlexGin . Предыдущая версия .
Re: Непустой выходной параметр - ваша реакция?
От: MasterZiv СССР  
Дата: 25.03.17 10:44
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


B>При одном из вызовов функции передается непустой вектор. Как, на ваш взгляд, функция должна отреагировать на это?


B>Что скажете?


vector<Something> GetSomething()
{
  vector<Something> output;
  // ...
  if( something_wrong() )
    throw std::system_error(result_code);

  return output;
}
Re: Непустой выходной параметр - ваша реакция?
От: Burbulis1978  
Дата: 07.04.17 15:37
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


B>При одном из вызовов функции передается непустой вектор. Как, на ваш взгляд, функция должна отреагировать на это?


B>1. Всегда очищать (лишнее действие, что не в духе плюсов).

B>2. Игнорировать, т.е. новые значения добавятся к старым ("не очистил сам дурак" — вполне в духе, но добавляет нестабильности).
B>3. Должен сработать assert (типа assert(output.empty)).
B>4. Вернуть ошибку/бросить исключение.
B>5. Оставлю комментарий со своим вариантом.

B>(Хотел сделать настоящее голосование, но получаю "500 — Internal server error". Зато здесь можно обсудить более развернуто).


B>Что скажете?

Что скажу я?Конечно я не мегагуру но предполагаю , что перед GetSomething, нужно произвести некоторые действия,
думаю что идиома нподобие RAII в данном случае была-бы полезна.
Ну и какоето время пока GetSom жив всегда можно запросить копию объекта. Никаких исключений только пожалуйста и ассертов, разрушите объект почём зря.

struct GetSom
{
std::vector<Something> temp; Очень важно определиться что это за фигня этот Something? Если это POD тип то что делать примерно ясно.

GetSom(vector<Something>& output)
{
size_t sz = output.size();
temp.resize(sz);
RtlCopyMemory(&temp[0],&output[0],sizeof(Something)*sz);
}

result_code operator()()
{
result_code GetSomething(temp);
}


};
Re: Непустой выходной параметр - ваша реакция?
От: AleksandrN Россия  
Дата: 13.04.17 15:00
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Есть функция:

B>
B>result_code GetSomething(vector<Something>& output);
B>


B>При одном из вызовов функции передается непустой вектор. Как, на ваш взгляд, функция должна отреагировать на это?


B>1. Всегда очищать (лишнее действие, что не в духе плюсов).

B>2. Игнорировать, т.е. новые значения добавятся к старым ("не очистил сам дурак" — вполне в духе, но добавляет нестабильности).
B>3. Должен сработать assert (типа assert(output.empty)).
B>4. Вернуть ошибку/бросить исключение.
B>5. Оставлю комментарий со своим вариантом.


Это зависит от того, что должна делать функция и как предполагается её использовать.

Например, если функцию предполагается вызывать в цикле для пополнения вектора, то очевидно, что вариант 2.
Если — для инициализации вектора перед использованием, то 1, но если предполагается, что вектор должен передаваться пустым, то 3, а если есть уверенность, что очищается в другом месте или в другом месте добавляются нужные данные — 2.
Если есть какие-то ограничение на размер — 4, если ограничение нарушено.
Может ещё быть вариант, что параметр — in/out.

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

Общего ответа, без привязки к задаче дать нельзя.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.