(ОБНОВЛЕНИЕ: этот вопрос связан с реализацией класса-оболочки, передаваемого по значению для объекта, который имеет разные значения для const Foo
и Foo
, на основе перемещения исключительно на твердом мнении людей здесь. До этого я раздавал const Foo*
и Foo*
, а когда пришла обертка, я поменял ее местами на Wrapper<Foo>
и const Wrapper<Foo>
. Теперь ясно, что механическая замена не имеет смысла, и мне понадобится что-то более сложное, например Wrapper<Foo>
и Wrapper<const Foo>
. ... хотя я пока не знаю, как это правильно написать. Извините за недоразумение, но я оставлю это здесь, так как на самом деле думаю, что это более показательно, чем многие вопросы.)
При рассмотрении этого вопроса казалось, что он сводится к будучи параллельным идее, что вы не можете этого сделать:
const Foo defaultFoo (6502);
const Foo theFoo (getConstFoo()); // returns const Foo for privilege reasons
if (theFoo.getBar() < 2012) {
theFoo = defaultFoo; // Error.
}
// ...you want to do const-safe methods with theFoo...
Подобно ссылкам, константное значение не может быть перенацелено. Выполнение следующего будет скомпилировано, но не будет тем, что я (в этом сценарии) намеревался:
Foo defaultFoo (6502);
Foo& theFooRef (getFooRef());
if (theFooRef.getBar() < 2000) {
theFooRef = defaultFoo; // Not an error, but not a retarget.
}
// ...you want to do stuff with theFooRef...
Кажется (насколько я понимаю), что reference_wrapper
может обойти это в эталонном случае с чем-то подобно:
Foo defaultFoo (6502);
std::reference_wrapper<Foo> theFooRef (getFooRef());
if (theFooRef.get().getBar() < 2000) {
theFooRef = std::ref(defaultFoo);
}
// ...do stuff with theFooRef.get() or employ implicit cast...
Мне интересно, есть ли там "value_wrapper
", который делает что-то подобное. Мне кажется разумным хотеть переменную, которая содержит элемент по значению, которое является константой, по причинам константной правильности... не потому, что вы не собираетесь ее менять. (например, отслеживание текущего узла в обходе дерева предварительного заказа, несмотря на наличие только постоянного доступа к узлам в этом дереве, где передача предыдущего узла в функцию — это то, как вы получаете новый узел) эм>
Если вы хотите быть неуклюжим, вы можете использовать std::pair<const Foo, bool>
и просто игнорировать bool
:
const Foo defaultFoo (6502);
std::pair<const Foo, bool> theFooBool (getConstFoo(), false);
if (theFooBool.first.getBar() < 2012) {
theFooBool = std::pair<const Foo, bool> (defaultFoo, false);
}
// ...do const-safe methods with theFooBool.first...
Но есть ли лучший способ решить эту проблему, помимо реализации моей собственной версии "value_wrapper
"?
theFoo = defaultFoo
, вы меняете значениеtheFoo
. Поэтому объявлять егоconst
неправильно. Если вам нужно иметь возможность изменить значение чего-либо, не объявляйте этоconst
. Если вы действительно хотите сделатьtheFoo
константным и вам нужно иметь возможность выбирать тот или инойFoo
при инициализацииtheFoo
, используйте функцию или лямбда-выражение для инкапсуляции логики выбора. - person James McNellis   schedule 13.07.2012getConstFoo
возвращаетFoo const
, не означает, чтоtheFoo
само должно быть константным; вы выполняете логическую копию, поэтому не имеет значения, является ли источник копии константным или нет. - person ildjarn   schedule 13.07.2012getConstFoo
, является плохой идеей, поскольку он препятствует семантике перемещения.) - person ildjarn   schedule 13.07.2012const Foo*
, вы могли вызывать только константные методы. Если кто-то вернул вамFoo*
, вы могли бы вызвать как константу, так и неконстанту. Вы можете передатьFoo*
методу, который принимаетconst Foo*
, но не наоборот. Теперь у меня есть объект-оболочка, который копирует по значению, и похоже, что он действительно разрушает контракт, именно так я и заметил. Я мог бы использовать хорошую ссылку на любое место, где была сделана оболочка, сохраняющая контракт const...! - person HostileFork says dont trust SE   schedule 13.07.2012std::reference_wrapper
. Указатели обеспечивают косвенность и переназначаются. Нет ничего плохого в использованииstd::reference_wrapper
, но вы говорите, что выполнение работы указателя — это что-то экзотическое. - person Luc Danton   schedule 13.07.2012