Есть ли что-то вроде std::value_wrapper, параллельное std::reference_wrapper?

(ОБНОВЛЕНИЕ: Этот вопрос связан с реализацией класса-оболочки, переданного по значению для объекта, который имеет различные значения для 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...

Как и ссылки, значение const не может быть перенаправлено. Выполнение следующего будет компилироваться, но не будет тем, что я (в этом сценарии) намеревался бы:

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 "там, где происходит нечто подобное. Мне кажется разумным хотеть переменную, которая содержит элемент по значению, который является константным по соображениям правильности констант... не потому, что вы не собираетесь его менять. (например, сохранение отслеживание текущего узла в Treewalk предварительного заказа, несмотря на то, что он имеет только постоянный доступ к узлам в этом дереве, где передача в предыдущем узле функции - это способ получения нового узла)

Если вы хотите быть неуклюжим, вы можете использовать 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 "?

2 ответа

Решение

Если вы хотите быть неуклюжим, вы можете использовать std::pair и просто игнорировать bool:

Это ясно объясняет, почему то, что вы хотите, не может быть сделано, потому что этот код не работает. я использовал const int скорее, чем const Foo, но это та же идея. Эта строка, где она разрывается:

theFooBool = std::pair<const Foo, bool> (defaultFoo, false);

Оператор присвоения копии не объявлен constпотому что по определению копирование-присваивание меняет объект. const это то, что вы используете, когда хотите, чтобы объект не был изменяемым.

Конечно, вы можете просто использовать std::reference_wrapper<const T>, который даст вам const доступ, но разрешить повторную привязку. Конечно, он не предлагает семантику значений, но это так близко, как вы собираетесь получить. В общем, большинству людей это не нужно или даже не нужно, так что оно еще не пришло.

Мои извинения, если я что-то упустил здесь. Но так как ваш вопрос не упоминает об этом, мне интересно, знаете ли вы, и рассмотрели:

Foo defaultFoo (6502);
std::reference_wrapper<const Foo> theFooRef (getFooRef());
if (theFooRef.get().getBar() < 2000) {
    theFooRef = std::cref(defaultFoo);
}
// ...do stuff with theFooRef.get() or employ implicit cast...
Другие вопросы по тегам