如果从不通过常量修改对实际const对象的引用的常量性,是否允许它们进行常量转换? [英] Is const-casting away const-ness of references to actual const objects permitted if they are never modified through them?
问题描述
我有一个抽象类,用于声明const和非const成员函数。为了便于讨论,我们将其看起来像这样:
I have an abstract class that declares const and non-const member functions. For the sake of discussion let's say it looks like this:
class record_interface
{
public:
virtual ~record_interface() = default;
virtual void set_foo(BoundedFloat) = 0;
virtual BoundedFloat get_foo() const = 0;
};
用作记录的高级表示形式,当保存到磁盘并通过电线传输时具有不同的表示形式。因此,大多数实现只需要将其成员转换为所需的高级表示形式即可。
This is used as a high-level representation of a record that has different representations when saved to disc and transferred via the wire. So most implementations just need to convert their members to the required high-level representation.
作为有效实现的示例,让我们定义 stored_record
。这用于以有损格式存储高级记录:
As an example of a valid implementation let's define stored_record
. This is used to store the high-level record in a lossy format:
struct stored_record
{
int16_t foo;
};
stored_record
可以实现 record_interface
,但是由于各种原因它不能(例如,它必须是 trivially_copyable
)。我们可以为它实现一个接口的包装器:
It makes sense that stored_record
can implement record_interface
but for various reasons it can't (eg. it needs to be trivially_copyable
). We can make a wrapper that implements the interface for it:
class record_wrapper : public record_interface
{
public:
record_wrapper(stored_record & wrapped)
: wrapped_(wrapped) {}
void set_foo(BoundedFloat value) final { wrapped_.foo = convert_to_int16(value); }
BoundedFloat get_foo() const final { return convert_from_int16(wrapped_.foo); }
private:
stored_record & wrapped_;
};
现在的问题是,当给定 const storage_record&时,我们不能使用包装器
因为
包装程序存储了可变引用。我们也不能使它存储非常量引用,因为它将无法实现非常量设置器功能。
Now the problem is that we can't use the wrapper when given a const stored_record &
since
the wrapper stores a mutable reference. We also can't make it store a non-const reference as it won't be able to implement the non-const setter function.
现在,我想知道它是否对提供一个工厂函数,使 const_cast
消失
a const storage_record&
的 const
,但还会返回 const包装器
,因此实际上不能修改引用:
Now I was wondering if it would be valid to provide a factory function that const_cast
s away
a const stored_record &
's const
but also returns a const wrapper
so that the reference cannot actually be modified:
record_wrapper make_wrapper(stored_record & wrapped) {return {wrapped}; }
record_wrapper const make_wrapper(stored_record const & wrapped) { return {const_cast<stored_record &>(wrapped)}; }
编辑:返回 const
record_wrapper
并不会真正将返回值限制为 const
,一种解决方案是返回 const_wrapper< record_wrapper>
或类似的东西。
EDIT: returning a const
record_wrapper
will not really restrict the returned value to be const
, a solution can be to return a const_wrapper<record_wrapper>
or something similar.
这是 const_cast
的有效用法还是由于 const_cast
取消了对实际const对象的引用的 const
-ness导致的不确定行为-即使它
Is this a valid usage of const_cast
or is it undefined behaviour due to const_cast
ing away the const
-ness of a reference to an actually const object - even though it is never modified through it.
推荐答案
每 https://en.cppreference.com/w/cpp/language/const_cast :
const_cast
可以形成对实际上是引用常量对象或引用或指向实际上引用易失性对象。通过非常量访问路径修改const对象,并通过非易失性 glvalue 导致未定义的行为。
const_cast
makes it possible to form a reference or pointer to non-const type that is actually referring to a const object or a reference or pointer to non-volatile type that is actually referring to a volatile object. Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.
因此,本身)(并且定义良好)。
So, the const_cast
itself is allowed (and well-defined), even though it would be undefined behavior to actually modify the object via the resulting non-const reference.
这篇关于如果从不通过常量修改对实际const对象的引用的常量性,是否允许它们进行常量转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!