-1

更新:这个问题源于一个包装类的实现,该包装类通过值传递一个对象,该对象对const Fooand具有不同的含义Foo,这一举动完全基于这里人们的强烈意见。之前,我一直在传递const Foo*Foo*当包装器来了,我把它换成了Wrapper<Foo>and const Wrapper<Foo>现在很明显,机械替换没有意义,我需要更复杂的东西,比如Wrapper<Foo>and 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”在那里做类似的事情。出于 const 正确性的原因,想要一个按值保存项目的变量对我来说似乎是合理的……而不是因为您不打算更改它。 (例如在前序树遍历中跟踪当前节点,尽管只有 const 访问该树中的节点,其中将前一个节点传递给函数是获取新节点的方式)

如果你想变得笨重,你可以使用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吗?

4

2 回答 2

2

如果我在这里忽略了一些东西,我深表歉意。但是由于您的问题没有提及,我想知道您是否知道并考虑过:

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...
于 2012-07-13T00:42:32.343 回答
1

如果你想变得笨重,你可以使用 std::pair 并忽略布尔:

这清楚地解释了为什么你想要的不能完成,因为这段代码不起作用。我使用const int了而不是const Foo,但这是相同的想法。这条线是它中断的地方:

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

未声明复制赋值运算符const,因为根据定义,复制赋值正在更改对象。const是当您希望对象不可更改时使用的。

当然,您可以只使用 a std::reference_wrapper<const T>,这将为您const提供访问权限,但允许重新绑定。当然,它不提供值语义,但这与您将获得的一样接近。一般来说,大多数人不需要甚至不想要这个,所以它还没有出现。

于 2012-07-13T00:41:40.137 回答