Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, Кодт, Вы писали:
NB>>>раз пошла такая пьянка, то и по optional спрошу. NB>>>какие-нибудь ограничения на размер или хранимые значения в нем есть? NB>>>а то не очень бы хотелось чтобы он для int занимал в два раза больше памяти чем нужно...
К>>Ну а куда ты вынесешь один бит признака "есть данные — нет данных"?
NB>у себя в велосипеде я использую особые значения вроде INT_MIN (конкретная стратегия применят флаг или некоторое значение задается в треитсах)
Типа такого: https://github.com/akrzemi1/compact_optional ? Вроде бы требования довольно распространённые, реализация несложная. Странно, что в std::optional не включили traits. Похоже, просто не нашлось желающих сделать соответствующее предложение.
Здравствуйте, PM, Вы писали:
К>>>Ну а куда ты вынесешь один бит признака "есть данные — нет данных"?
NB>>у себя в велосипеде я использую особые значения вроде INT_MIN (конкретная стратегия применят флаг или некоторое значение задается в треитсах)
PM>Типа такого: https://github.com/akrzemi1/compact_optional ? Вроде бы требования довольно распространённые, реализация несложная.
реализация другая, но смысл такой.
PM>Странно, что в std::optional не включили traits. Похоже, просто не нашлось желающих сделать соответствующее предложение.
тут проблема в том что треитсы (или таги) придется или вторым шаблонным параметром передавать,
или вместо optional< int > использовать optional< some_strategy_tag<int> > (some_strategy_tag используется только для недефолтовых треитсов)
возможно решили что оно того не стоит.
Здравствуйте, night beast, Вы писали:
PM>>Странно, что в std::optional не включили traits. Похоже, просто не нашлось желающих сделать соответствующее предложение.
NB>тут проблема в том что треитсы (или таги) придется или вторым шаблонным параметром передавать, NB>или вместо optional< int > использовать optional< some_strategy_tag<int> > (some_strategy_tag используется только для недефолтовых треитсов) NB>возможно решили что оно того не стоит.
Здравствуйте, PM, Вы писали:
NB>>тут проблема в том что треитсы (или таги) придется или вторым шаблонным параметром передавать, NB>>или вместо optional< int > использовать optional< some_strategy_tag<int> > (some_strategy_tag используется только для недефолтовых треитсов) NB>>возможно решили что оно того не стоит.
PM>Насколько я понял из обсуждения https://groups.google.com/a/isocpp.org/forum/m/#!topic/std-proposals/46J1onhWJ-s/discussion дополнительная стратегия для optional может поменять его семантику, что привело бы к существенным изменениям в существующем std::optional, так что дальше обсуждения дело не пошло.
как я понял, предлагали еще в 12г (когда не было std::optional), но походу, забили на это дело ))
Разница в том, что в варианте с вызовом лямбды (или даже простой функции) — это всё одно выражение (expression), и есть гарантия что временные объекты живут до конца выполнения выражения в котором были созданы.
Во втором же случае, потребовалась бы продление времени жизни временной переменной до конца scope — что в данном случае нетривиально, так как потребовало бы от компилятора запоминание того какого типа значение в итоге забиндилось, сколько оно занимает на стэке, и в конце scope в зависимости от варианта — d1 или d2 — вызывать правильный деструктор и правильно очищать стэк.
tdiff:
NI>>Разница в том, что во втором случае к моменту вызова f ссылка x указывает на мёртвый объект.
T>Почему, если base&& должна продлевать время жизни temporary?
Всё дело в мутном понятии "temporary". Под ним подразумеваются сразу и временный объект и выражение, которое обозначает этот объект. Выражению, которое мы используем в качестве инициализатора ссылки на временный объект, недостаточно просто ссылаться на данный объект, чтоб его время жизни продлялось, — само выражение должно быть "temporary" (если б продление времени жизни временного объекта работало для любого выражения-инициализатора, то как минимум возникли бы очевидные сложности с проверкой, является ли объект временным).
Выражение является temporary только если в правилах для него явно указано, что оно temporary, либо если оно непосредственно создаёт и возвращает некий temporary object, либо если оно эквивалентно чему-то, что является temporary (если temporary обернуть в круглые скобки, то получившееся выражение тоже будет temporary). Разумеется, нормальной формализацией тут и не пахнет, и одно лишь чтение стандарта не приводит к пониманию что есть что; нужно просто знать, что стандартизаторы имели в виду.
T>У меня есть догадка, что происходит что-то вроде: T>1. создаётся temporary d1() с типом d1&&
Выражения никогда не имеют ссылочный тип. Типом выражения d1() будет d1.
T>2. тип этого объекта конвертируется в base&&
Формально там prvalue типа d1 преобразуется к xvalue типа base. Исходное prvalue является temporary, а получившееся xvalue уже не является temporary (хотя оно тоже ссылается на временный объект).
T>3. результатом ternary является base&&, которая продлевает время жизни d1
Нет там никаких ссылок.
T>этой ссылкой инициализируется ссылка base&& x, которая почему-то уже не продлевает жизни d1
x инициализируется non-temporary выражением, поэтому продление не применяется.
Здравствуйте, tdiff, Вы писали:
T>хочу, чтобы стек выглядел вот так: T>[ссылка на объект ниже] T>[d1 или d2] T>и время жизни d1 или d2 совпадало с текущим скоупом.
Шаблоны, вариадики и обработку случая, когда максимальный рзмер буфера меньше или равен sizeof(tAlignmentAs) добавить по вкусу
А вообще-то, писать так как тебе не хочется проще и понятнее всего
За одно ещё и от динамического полиморфизма избавишься
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Erop:
E>Что мешает написать то, что ты хочешь, прямо?
Много букв и error prone, если не знать, как правильно создавать и удалять вручную объекты с правильным соблюдением всех па.
E>Шаблоны, вариадики и обработку случая, когда максимальный рзмер буфера меньше или равен sizeof(tAlignmentAs) добавить по вкусу
Другое дело, что вряд ли всё это вообще нужно. Обычно такие объекты или редко создаются или сами по себе настолько тяжелы, что подобная "оптимизация" реально ничего заметного не даст.
Здравствуйте, tdiff, Вы писали:
EP>>Во втором же случае, потребовалась бы продление времени жизни временной переменной до конца scope T>Спасибо за подробный ответ, но по-моему у нас есть гарантия, что const & / && — ссылки продлевают жизнь временным объектам.
Здравствуйте, N. I., Вы писали:
NI>Всё дело в мутном понятии "temporary". Под ним подразумеваются сразу и временный объект и выражение, которое обозначает этот объект. Выражению, которое мы используем в качестве инициализатора ссылки на временный объект, недостаточно просто ссылаться на данный объект, чтоб его время жизни продлялось, — само выражение должно быть "temporary" (если б продление времени жизни временного объекта работало для любого выражения-инициализатора, то как минимум возникли бы очевидные сложности с проверкой, является ли объект временным). NI> ... NI> Выражение является temporary только если в правилах для него явно указано, что оно temporary, либо если оно непосредственно создаёт и возвращает некий temporary object NI> ... NI>Формально там prvalue типа d1 преобразуется к xvalue типа base. Исходное prvalue является temporary, а получившееся xvalue уже не является temporary (хотя оно тоже ссылается на временный объект). NI> ... NI>x инициализируется non-temporary выражением, поэтому продление не применяется.
Спасибо за подробный ответ. Это действительно довольно мутно Например, почему "получившееся xvalue уже не является temporary"? Беглый поиск "temporary expression" по стандарту вообще находит только одно упоминание.
Здравствуйте, tdiff, Вы писали:
T>Привет
T>Хочется в зависимости от условия создавать на стеке объекты разных подтипов одного общего класса, но пока не получается: T>
T>class base { virtual void f() const = 0;};
T>class d1 : public base { void f() const override {...} };
T>class d2 : public base { void f() const override {...} };
T>const base& obj = true ? (const base&)d1() : d2();
T>obj.f();
T>
... T>а создавать без повода объекты на хипе тоже как-то не круто.
tdiff:
T>Например, почему "получившееся xvalue уже не является temporary"?
Потому что не указано, что оно temporary Вот, смотри:
__declspec(dllimport) X *dll_func(X &&, X *);
int main()
{
auto &&x = static_cast<X &&>(*dll_func(X(), new X));
....
}
Теоретически dll_func может вернуть указатель на временный объект, созданный выражением X(), но она также может вернуть и что-нибудь иное — например, указатель на объект, созданный выражением new X. Как компилятор узнает, ссылается ли выражение static_cast<X &&>(*dll_func(X(), new X)) на временный объект? Очевидно, что для продления времени жизни временного объекта как минимум требуется какой-то признак того, что объект действительно является временным. Если объект берётся из какого-то выражения, то таким признаком служит принадлежность выражения к определённому виду. Если выражение к соответствующему виду не принадлежит, то время жизни объекта, на который оно ссылается, продляться не будет (независимо от того, является объект временным или нет).
Здравствуйте, Erop, Вы писали:
T>>хочу, чтобы стек выглядел вот так: T>>[ссылка на объект ниже] T>>[d1 или d2] T>>и время жизни d1 или d2 совпадало с текущим скоупом. E>Что мешает написать то, что ты хочешь, прямо?
Видимо желание узнать о готовом решении а-ля boost/std::variant превалирует над желанием лисапедить
Здравствуйте, N. I., Вы писали:
NI>Много букв и error prone, если не знать, как правильно создавать и удалять вручную объекты с правильным соблюдением всех па.
Конкретно этот трудно довольно неправильно использовать, если ещё и operator = удалить.
NI>Другое дело, что вряд ли всё это вообще нужно. Обычно такие объекты или редко создаются или сами по себе настолько тяжелы, что подобная "оптимизация" реально ничего заметного не даст.
Казалось бы, если тяжелы, то стека в два раза меньше съестся...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Видимо желание узнать о готовом решении а-ля boost/std::variant превалирует над желанием лисапедить
Я так понимаю, что всё это под флагом борьбы с оверхедом же?
Конечно подозрительная такая бескомпромиссная борьба, но фиг его знает-то, может людям реально надо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>Видимо желание узнать о готовом решении а-ля boost/std::variant превалирует над желанием лисапедить
E>Я так понимаю, что всё это под флагом борьбы с оверхедом же? E>Конечно подозрительная такая бескомпромиссная борьба, но фиг его знает-то, может людям реально надо...
Здравствуйте, tdiff, Вы писали:
T>Ну как обычно, ради состояния
А динамический полиморфизм для чего?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском