Re[3]: хитрый возврат объекта из функции
От: nhie  
Дата: 27.01.11 14:48
Оценка: -1 :)
Здравствуйте, l33thaxor, Вы писали:

L>Да, это прикольно. Пока только один недостаток вижу (если считать, что массив в data_factory правельного размера и выровнен): если требуется возвратить data из функции, вызывающей fetch_data, то нужно либо делать копирование либо протаскивать data_factory. Т.е.:


А, так вам нужно "прикольно", что ж вы сразу-то не сказали Имхо, фокус с аргумент по умолчанию действительно прикольный, но реально такой код я бы использовать не стал: невидимый объект, дохнущий по окончанию full expression — отлично спрятанные грабли... Плюс нарушение стандарта на тему изменения temporaries (mutable это конечно ловко, но это же хак). Но если уж сильно хочется использовать этот вариант, то почему просто не передавать data() как аргумент по умолчанию и делать const_cast<data> — стандарт в обоих случаях нарушается одинаково.

    data const & fetch_data( string const & request, data const & tmp = data() )
    {
        data* p = const_cast<data*>(&tmp);
        return tmp;
    }


Но невидимые грабли это жестоко
Re: хитрый возврат объекта из функции
От: night beast СССР  
Дата: 27.01.11 05:23
Оценка: 3 (1)
Здравствуйте, l33thaxor, Вы писали:

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


такой вариант потестируй:
#include<memory>

template<typename T>
struct data_factory {

   mutable unsigned char data[100];

   data_factory () {}

   T & create ( T const & src ) const {
       return *( new(data) T(src) );
   }
};

data const & fetch_data( string const & request, data_factory<data> const & tmp = data_factory<data>( ) )
   return tmp.create( 1 );
}
Re[5]: хитрый возврат объекта из функции
От: Pavel Dvorkin Россия  
Дата: 26.01.11 11:10
Оценка: 1 (1)
Здравствуйте, l33thaxor, Вы писали:

L>В этом случае, когда storage создает новый объект, его прийдется выделять на хипе, а хотелось бы обойтись стеком.


Ну вообще-то вернуть хоть ссылку, хоть указатель на объект, созданный на стеке внутри функции, вне ее — это никуда не годится.

Вопрос — что значит "создает новый объект" ? Один раз вызвали, не нашел, создал. Второй раз — то же ? Первый созданный объект к этому времени должен еще жить? или же можно его память использовать для второго ? Иными словами, их много может быть или в любой момент только один ? Если один — можно банально глобальную переменную завести.
With best regards
Pavel Dvorkin
Re[3]: хитрый возврат объекта из функции
От: nhie  
Дата: 27.01.11 14:53
Оценка: 1 (1)
В конце концов, я бы наверное сделал так, вроде вышло удобно в использовании.

    struct data
    {
        int x, y;
    };

    struct fetcher
    {
        fetcher(string const& request)
        {
            if (false)
            {
                p = (data*)0xBAD; // existing, take from storage
                return;
            }
            d = data(); // copy
            p = &d;
        }

        data d;
        data* p;
        data const* operator->() { return p; }
    };

    void use()
    {
        fetcher f("req");
        f->x;
        fetcher f2("req2");
        f2->y;
    }
хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 01:13
Оценка:
Вот такое дело. Допустим у класса storage есть функция fetch_data, которая возвращает объекты типа data по запросу:
data storage::fetch_data(string const & request);

Пока что data возвращается по значению. Но в большинстве случаев оказывается, что можно было бы возвратить и ссылку на data, сохраненный в storage:
data const & storage::fetch_data(string const & request);

И это было бы гораздо эффективнее текущей версии, так как не надо делать копию data.

Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?
Re: хитрый возврат объекта из функции
От: Ops Россия  
Дата: 26.01.11 01:27
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Вот такое дело. Допустим у класса storage есть функция fetch_data, которая возвращает объекты типа data по запросу:

L>
L>data storage::fetch_data(string const & request);
L>

L>Пока что data возвращается по значению. Но в большинстве случаев оказывается, что можно было бы возвратить и ссылку на data, сохраненный в storage:
L>
L>data const & storage::fetch_data(string const & request);
L>

L>И это было бы гораздо эффективнее текущей версии, так как не надо делать копию data.

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


shared_ptr подойдет?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 01:30
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>shared_ptr подойдет?


Каким образом? В storage объекты хранятся не ввиде shared_ptr.
Re[3]: хитрый возврат объекта из функции
От: Ops Россия  
Дата: 26.01.11 01:36
Оценка:
Здравствуйте, l33thaxor, Вы писали:

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


Ops>>shared_ptr подойдет?


L>Каким образом? В storage объекты хранятся не ввиде shared_ptr.


http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/sp_techniques.html#static
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[4]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 01:44
Оценка:
Здравствуйте, Ops, Вы писали:

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


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


Ops>>>shared_ptr подойдет?


L>>Каким образом? В storage объекты хранятся не ввиде shared_ptr.


Ops>http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/sp_techniques.html#static


В этом случае, когда storage создает новый объект, его прийдется выделять на хипе, а хотелось бы обойтись стеком. Да и shared_ptr со своим deleter'ом выглядить как то тяжеловато тоже. Больше никаких нет вариантов?
Re[5]: хитрый возврат объекта из функции
От: Ops Россия  
Дата: 26.01.11 02:09
Оценка:
Здравствуйте, l33thaxor, Вы писали:

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


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


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


Ops>>>>shared_ptr подойдет?


L>>>Каким образом? В storage объекты хранятся не ввиде shared_ptr.


Ops>>http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/sp_techniques.html#static


L>В этом случае, когда storage создает новый объект, его прийдется выделять на хипе, а хотелось бы обойтись стеком. Да и shared_ptr со своим deleter'ом выглядить как то тяжеловато тоже. Больше никаких нет вариантов?


Ну так все зависит от того, насколько тяжелые объекты и как потом с ними работают. А вместо выделения в хипе можно использовать пул для этих объектов, или даже просто placement new — тут все от многопоточности зависит.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: хитрый возврат объекта из функции
От: _nn_  
Дата: 26.01.11 10:10
Оценка:
Здравствуйте, l33thaxor, Вы писали:

Имеется возможность произвести move ?
Возможно это может будет эффективней всего.

С++0х ждать для move не обязательно, можно его реализовать вручную как в std::auto_ptr делается.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: хитрый возврат объекта из функции
От: ariets  
Дата: 26.01.11 11:42
Оценка:
Здравствуйте, l33thaxor, Вы писали:

Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


const data &fetch_data( const std::string &request )
{
 if( is_data( request ) )
 {
  return get_data( request );
 }

 static const data emptyData;
 return emtyData;
}
Re[2]: хитрый возврат объекта из функции
От: Хвост  
Дата: 26.01.11 12:16
Оценка:
Здравствуйте, ariets, Вы писали:

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


A>Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?



A>
...
A> static const data emptyData;
A> return emtyData;
A>}
A>


у вас же переменная static, возвращайте всегда ссылку.
People write code, programming languages don't.
Re[3]: хитрый возврат объекта из функции
От: Хвост  
Дата: 26.01.11 12:19
Оценка:
Здравствуйте, Хвост, Вы писали:

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


упс, я думал вы топикстартер. как удалить сообщение?
People write code, programming languages don't.
Re[2]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 15:29
Оценка:
Здравствуйте, ariets, Вы писали:

A>
A>const data &fetch_data( const std::string &request )
A>{
A> if( is_data( request ) )
A> {
A>  return get_data( request );
A> }

A> static const data emptyData;
A> return emtyData;
A>}
A>


Статический объект не подходит. В этом случае не будет работать даже простейшая последовательность двух вызовов fetch_data:
data const & d1 = fetch_data(r1);
data const & d2 = fetch_data(r2);  // d1 is clobbered
Re[6]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 15:30
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Вопрос — что значит "создает новый объект" ? Один раз вызвали, не нашел, создал. Второй раз — то же ? Первый созданный объект к этому времени должен еще жить? или же можно его память использовать для второго ?


Должен жить. Память переиспользовать нельзя.
Re[2]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 15:34
Оценка:
Здравствуйте, _nn_, Вы писали:

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


__>Имеется возможность произвести move ?

__>Возможно это может будет эффективней всего.

__>С++0х ждать для move не обязательно, можно его реализовать вручную как в std::auto_ptr делается.


Непонятно, как мне это поможет. Мне нужно оптимизировать для случая возврата существующего объекта по ссылке. Это fast path. Возврат по значению, когда происходит создание нового объекта и копирование его при возврате из функции, это slow path. Она происходит редко и его оптимизировать не надо.
Re[7]: хитрый возврат объекта из функции
От: Pavel Dvorkin Россия  
Дата: 26.01.11 15:48
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Вопрос — что значит "создает новый объект" ? Один раз вызвали, не нашел, создал. Второй раз — то же ? Первый созданный объект к этому времени должен еще жить? или же можно его память использовать для второго ?


L>Должен жить. Память переиспользовать нельзя.


Тогда я не понимаю, как ты хочешь вернуть данные, расположенные на стеке. Допустим на минуту, что это возможно. Сделать-то как ? Нельзя же описать неопределенное число автоматических переменных.
With best regards
Pavel Dvorkin
Re[8]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 16:27
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

L>>Должен жить. Память переиспользовать нельзя.


PD>Тогда я не понимаю, как ты хочешь вернуть данные, расположенные на стеке. Допустим на минуту, что это возможно. Сделать-то как ? Нельзя же описать неопределенное число автоматических переменных.


Я не хочу вернуть данные на стеке. Вопрос заключался в следующем: если данные уже существуют в storage, то вернуть их так же быстро как по сслыке, если же данных нет, то создать из и вернуть по значению.

На самом деле вот один вариант интерфейса, который удовлетворяет данному требованию. Я не хотел его сразу приводить, думал, что кто-нибудь приведет что-нибудь лучше.
// temp_obj - [in/out] указатель на временный объект, переданный из вызывающей стороны,
// в который будет положен объект data, если нельзя вернуть ссылку и необходимо создать новый объект
data const * storage::fetch_data(data * temp_obj, string const & request) {
    if (data const * existing = retrieve_data(request)) {
        return existing;
    }

    create_data(request).swap(*temp_obj);
    return temp_obj;
}

// вызов
data temp_obj;
data const * fetched = storage.fetch_data(&temp_obj, request);
// работаем с fetched
// при выходе из scope, temp_obj освободит объект, который мог создать fetch_data

Здесь удовлетворены требования по производительности. Но мне этот интерфейс не нравится. Во-первых, вызов fetch_data немного кривой получается. А во-вторых, получается, что fetch_data имеет некоторый неоднозначный side effect.

Можно ли реализовать подобную идею с более приличным интерфейсом.
Re[9]: хитрый возврат объекта из функции
От: Pavel Dvorkin Россия  
Дата: 26.01.11 17:04
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Здравствуйте, Pavel Dvorkin, Вы писали:


L>>>Должен жить. Память переиспользовать нельзя.


PD>>Тогда я не понимаю, как ты хочешь вернуть данные, расположенные на стеке. Допустим на минуту, что это возможно. Сделать-то как ? Нельзя же описать неопределенное число автоматических переменных.


L>Я не хочу вернуть данные на стеке. Вопрос заключался в следующем: если данные уже существуют в storage, то вернуть их так же быстро как по сслыке, если же данных нет, то создать из и вернуть по значению.


L>На самом деле вот один вариант интерфейса, который удовлетворяет данному требованию. Я не хотел его сразу приводить, думал, что кто-нибудь приведет что-нибудь лучше.


<skipped>

L>Здесь удовлетворены требования по производительности. Но мне этот интерфейс не нравится. Во-первых, вызов fetch_data немного кривой получается. А во-вторых, получается, что fetch_data имеет некоторый неоднозначный side effect.


L>Можно ли реализовать подобную идею с более приличным интерфейсом.


Честно говоря, мне все это совсем не нравится. Создается какой-то непонятный (и, возможно, ненужный) объект, потом внутри в него пересылают данные из вновь созданного, и все это ради того, чтобы этот объект потом мог сам удалиться на выходе из scope.

Я бы просто сделал. Вернул бы указатель то ли на найденный, то ли на прямо там созданный объект и завел бы еще один параметр, указывающий был ли объект создан или нет. Если нет — delete его и все дела.


data const * storage::fetch_data(string const & request, bool& wasFound) {
    if (data const * existing = retrieve_data(request)) {
        wasFound = true;
        return existing;
    }
    wasFound = false
    return create_data(request)
}

...
bool wasFound;
data const * result = fetch_data(request,wasFound);
// use result
if(!wasFound)
  delete result;


А можно чуть похитрее


class data_and_bool
{
  data* result;
  bool wasFound;
  ~data_and_bool()
  {
    if(!wasFound)
     delete data;
  }
};

data_and_bool storage::fetch_data(string const & request) {
    data_and_bool dab;
    if (data const * existing = retrieve_data(request)) {
        dab.wasFound = true;
        dab.result = existing;
    }
  else {
    dab.wasFound = false;
    dab.result = create_data(request);
}
  return dab;
}

data_and_bool dab = storage::fetch_data(request);
// и пусть деструктор уничтожает данные на выходе из scope, если они были созданы


}


Естественно, не компилировал, так что за возможные ошибки сорри. Считай это псевдокодом.
With best regards
Pavel Dvorkin
Re[10]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 17:43
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Я бы просто сделал. Вернул бы указатель то ли на найденный, то ли на прямо там созданный объект и завел бы еще один параметр, указывающий был ли объект создан или нет. Если нет — delete его и все дела.


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

Если бы хип был приемлимым, то я бы выбрал вариант с shared_ptr, который был упомянут в первых ответах.
Re[11]: хитрый возврат объекта из функции
От: Pavel Dvorkin Россия  
Дата: 26.01.11 17:58
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Такая идея мне в голову приходила, но хотелось бы обойтись без создания объектов на хипе, если можно ограничиться стеком. В том интерфейсе, который я привел (с временным temp_obj), объекты создаются на стеке.


Хм, а create_data где его создает ?
With best regards
Pavel Dvorkin
Re[12]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 26.01.11 18:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


L>>Такая идея мне в голову приходила, но хотелось бы обойтись без создания объектов на хипе, если можно ограничиться стеком. В том интерфейсе, который я привел (с временным temp_obj), объекты создаются на стеке.


PD>Хм, а create_data где его создает ?


На стеке и возвращает по значению.
Re: хитрый возврат объекта из функции
От: nhie  
Дата: 26.01.11 19:05
Оценка:
Ну если именно на стеке, и копировать при необходимости, то можно как-то так (компилятором не проверял):

struct result
{
    data* p_existing;
    data copied;
    void set(data* p) { p_existing = p; }
    void set(const data& d) { copied = d; p_existing = 0; }
    data& get() { return (p_existing != 0) ? *p_existing : copied; }
};

void fetch_data(string const & request, result& res)
{
    if (data* existing = retrieve_data(request)) {
        res.set(existing);
    }

    res.set( create_data(request) );
}

void use()
{
    result res;
    fetch_data(request, res);
    res.get().#; // use data, either copied or existing
}
Re[2]: хитрый возврат объекта из функции
От: nhie  
Дата: 26.01.11 19:54
Оценка:
А ещё можно p_existing вместо 0 заменить на &copied, наверное проще будет. Ну и интерфейс подточить по вкусу
Re: хитрый возврат объекта из функции
От: Аноним  
Дата: 26.01.11 22:41
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Вот такое дело. Допустим у класса storage есть функция fetch_data, которая возвращает объекты типа data по запросу:

L>
L>data storage::fetch_data(string const & request);
L>

L>Пока что data возвращается по значению. Но в большинстве случаев оказывается, что можно было бы возвратить и ссылку на data, сохраненный в storage:
L>
L>data const & storage::fetch_data(string const & request);
L>

L>И это было бы гораздо эффективнее текущей версии, так как не надо делать копию data.

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


Если ты в объекте типа data который тебе возвращается не будешь ничего менять и вызывать только константные методы, то
почему бы не
const data& ref = storage::fetch_data(string const & request);
ну а если уж бандитизмом заниматся во благо производительности то
const data& ref = storage::fetch_data(string const & request);
data& ref2 = const_cast<data&>(ref);

Хотя приведенный тобой вариант с передачей указателя на объект типа data в функцию, по моему мнение,вполне себе ничего.
Только я бы ссылку передавал )
Re[2]: хитрый возврат объекта из функции
От: l33thaxor  
Дата: 27.01.11 07:14
Оценка:
Здравствуйте, night beast, Вы писали:

NB>такой вариант потестируй:

NB>
NB>data const & fetch_data( string const & request, data_factory<data> const & tmp = data_factory<data>( ) )
NB>   return tmp.create( 1 );
NB>}
NB>


Да, это прикольно. Пока только один недостаток вижу (если считать, что массив в data_factory правельного размера и выровнен): если требуется возвратить data из функции, вызывающей fetch_data, то нужно либо делать копирование либо протаскивать data_factory. Т.е.:
data const & proxy_fetch(string const & request) {
    return fetch_data(request);  // бум!
}

data proxy_fetch(string const & request) {
    return fetch_data(request);  // OK
}

data const & proxy_fetch(string const & request, data_factory<data> const & tmp = data_factory<data>())
{
    return fetch_data(request, tmp);  // OK
}
Re[3]: хитрый возврат объекта из функции
От: night beast СССР  
Дата: 27.01.11 07:26
Оценка:
Здравствуйте, l33thaxor, Вы писали:

NB>>такой вариант потестируй:

NB>>
NB>>data const & fetch_data( string const & request, data_factory<data> const & tmp = data_factory<data>( ) )
NB>>   return tmp.create( 1 );
NB>>}
NB>>


L>Да, это прикольно. Пока только один недостаток вижу (если считать, что массив в data_factory правельного размера и выровнен): если требуется возвратить data из функции, вызывающей fetch_data, то нужно либо делать копирование либо протаскивать data_factory. Т.е.:

L>data const & proxy_fetch(string const & request) {
L>    return fetch_data(request);  // бум!
L>}


да.
ссылка живет до конца выражения. вариант:
data const & ref = fetch_data(request);
// use ref

не пройдет.
чтобы работало надо в любом случае или передавать объект/буфер в функцию, или возвращать по значению, или отказаться от стека.
от этого не уйти.
Re[3]: хитрый возврат объекта из функции
От: night beast СССР  
Дата: 27.01.11 07:46
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Да, это прикольно. Пока только один недостаток вижу (если считать, что массив в data_factory правельного размера и выровнен): если требуется возвратить data из функции, вызывающей fetch_data, то нужно либо делать копирование либо протаскивать data_factory. Т.е.:


забыл еще. в деструкторе фабрики надо деструктор вызывать, есть создание прошло.
Re[3]: хитрый возврат объекта из функции
От: gegMOPO4  
Дата: 27.01.11 21:28
Оценка:
Здравствуйте, l33thaxor, Вы писали:
L>Статический объект не подходит. В этом случае не будет работать даже простейшая последовательность двух вызовов fetch_data:
L>
L>data const & d1 = fetch_data(r1);
L>data const & d2 = fetch_data(r2);  // d1 is clobbered
L>


Заведите статический массив на 10 или 100 элементов и используйте циклически. Для произвольного времени жизни результата не подойдёт, но в этом случае не подойдёт и любой из предложенных методов.
Re: хитрый возврат объекта из функции
От: alexeiz  
Дата: 28.01.11 05:07
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


Можно попробовать создать variant класс, который будет содержать либо ссылку (указатель) на объект либо копию объекта data.
template <typename T>
class ptr_value : boost::variant<T, const T *>
{
private:
   typedef boost::variant<T, const T *>  base_t;

   struct value_visitor : boost::static_visitor<const T *>
   {
       const T * operator()(const T & val) const
       {
           return &val;
       }

       const T * operator()(const T * ptr) const
       {
           return ptr;
       }
   };

   const T * get_ptr() const
   {
       return boost::apply_visitor(value_visitor(), static_cast<const base_t &>(*this));
   }

public:
   explicit
   ptr_value(const T & val)
       : base_t(val)
   {}

   explicit
   ptr_value(const T * ptr)
       : base_t(ptr)
   {}

   const T * operator->() const
   {
       return get_ptr();
   }

   const T & operator*() const
   {
       return *get_ptr();
   }
};

Тогда fetch_data перепишется как-то так:
ptr_value<data> storage::fetch_data(string const & request) {
    if (data const * existing = retrieve_data(request)) {
        return ptr_value<data>(existing);
    }

    return ptr_value<data>(create_data(request));
}
Re: хитрый возврат объекта из функции
От: testpu  
Дата: 10.02.11 12:48
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Вот такое дело. Допустим у класса storage есть функция fetch_data, которая возвращает объекты типа data по запросу:

L>
L>data storage::fetch_data(string const & request);
L>

L>Пока что data возвращается по значению. Но в большинстве случаев оказывается, что можно было бы возвратить и ссылку на data, сохраненный в storage:
L>
L>data const & storage::fetch_data(string const & request);
L>

L>И это было бы гораздо эффективнее текущей версии, так как не надо делать копию data.

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?

Как такой вариант?
data const & storage::fetch_data(string const & request, data& outForDataThatWasn'tFound, bool& dataFound )
{
...
   if(found)
   {
       dataFound = true;
       return dataThatWasFound;
   }
   else
   {
      outForDataThatWasn'tFound = newdata;
      dataFound = false;
      return outForDataThatWasn'tFound;
   }      
}
Re: хитрый возврат объекта из функции
От: Velheart Беларусь  
Дата: 10.02.11 17:08
Оценка:
Здравствуйте, l33thaxor, Вы писали:

boost::optional<const data&> storage::fetch_data(string const & request);


Не ?
Re: хитрый возврат объекта из функции
От: sidorov18 США  
Дата: 11.02.11 07:59
Оценка:
Здравствуйте, l33thaxor, Вы писали:

L>Но иногда storage не может найти данные по запросу, и он их создаёт. И в этом случае по ссылке возвратить data уже нельзя. Именно поэтому текущая версия fetch_data возвращает по значению. Вопрос: как так возвратить data, чтобы в в большинстве случаев не делать копирования, а делать только в тех редких случаях, когда приходится?


уверены, что RVO/NRVO не пройдет?
да и насколько тяжелый data? если там просто данные байт на 64 быстрее будет работать копирование на стеке, чем одно выделение на куче.
Re[3]: хитрый возврат объекта из функции
От: sidorov18 США  
Дата: 11.02.11 08:02
Оценка:
Здравствуйте, l33thaxor, Вы писали:


L>Да, это прикольно. Пока только один недостаток вижу (если считать, что массив в data_factory правельного размера и выровнен): если требуется возвратить data из функции, вызывающей fetch_data, то нужно либо делать копирование либо протаскивать data_factory. Т.е.:


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