为什么 const_cast 需要声明你要转换的内容?

发布于 2024-10-06 17:18:14 字数 960 浏览 0 评论 0原文

根据标准 (§5.2.11),const_cast 会丢弃 cv 限定符(const 或 volatile)。

这是一个简单的例子。首先,声明两个带有指针和引用的函数:

class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);

然后创建一个对 const 的引用:

Bar b;
const Bar& cb = b;

然后您可以使用适当的 const_cast 来调用任一函数:

foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));

这是我的问题:因为 const_cast 无法执行其他强制转换的设计目的,你要投射的内容不是很明显吗?换句话说,为什么该语言不允许我简单地说:

foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));

我只能想到以下两个原因:

a)当我尝试做一些疯狂的事情时,编译器应该阻止我,例如:

foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));

并强制我显式声明我向它投射的类型可以防止我行为不当。我发现这个(假设的)解释很弱,因为如果语言倾向于允许我写下一些错误的东西只是为了让编译器纠正我,那就太奇怪了。

b) 如果变量既是 const 又是 volatile,则可能存在歧义。在这种情况下,编译器将无法判断我是否试图放弃其中一个或另一个(或两者)。

是这个原因,还是还有其他原因?

According to the standard (§5.2.11) a const_cast casts away cv-qualifiers (const or volatile).

Here's a simple example. First you declare two functions taking a pointer and a reference:

class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);

then you create a reference-to-const:

Bar b;
const Bar& cb = b;

and then you can call either function by using the appropriate const_cast:

foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));

Here's my question: since const_cast cannot do what the other casts were designed for, isn't it obvious what you're casting to? In other words, why doesn't the language allow me to simply say:

foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));

I can think of only the following two reasons:

a) The compiler should stop me when I try to do something crazy, like:

foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));

and by forcing me to explicitly state the type I'm casting to it can then keep me from misbehaving. I find this (hypothetical) explanation weak, since it would be bizarre if the language favored allowing me to write down something wrong only to have the compiler correct me.

b) There is a possible ambiguity if the variable is both const and volatile. In that case the compiler would have no way of telling if I'm trying to cast away the one or the other (or both).

Is that why, or is there another reason?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

抚笙 2024-10-13 17:18:14

const_cast 可用于添加或删除 constvolatile 限定符。因此,如果允许这样的语法,则以下所有内容都将是 const_cast<>(&cb) 的合法目标类型:

Bar*                 (1)
const Bar*           (2)
volatile Bar*        (3)
const volatile Bar*  (4)

您想要(1)(2) 通常很愚蠢,但可以想象它可能出现在某个地方,也许出现在某些模板代码中。 (3)(4) 确实是问题所在:您可以删除 const 限定并添加 易失性资格全部通过一次演员。

您可以将现有的 const_cast 替换为一对强制转换:const_castvolatile_cast,并禁止 case (2) ;那么您可以在没有目标类型的情况下使用它们中的任何一个。然而,了解强制转换表达式的类型就更困难了。要了解强制转换表达式是否添加或删除限定条件,您必须知道源表达式的类型是什么。

您没有理由不能使用函数模板来获得您想要的内容:

template <typename T>
T* remove_const(const T* p) {
    return const_cast<T*>(p);
}

您可以轻松地为 remove_volatile 以及 add_constadd_volatile 编写类似的函数>,两者都是隐式的。

const_cast can be used to add or remove const and volatile qualifiers. So, if such a syntax were allowed, all of the following would be legitimate target types of const_cast<>(&cb):

Bar*                 (1)
const Bar*           (2)
volatile Bar*        (3)
const volatile Bar*  (4)

You intend (1). (2) is usually silly, but it is conceivable that it might occur somewhere, perhaps in some template code. (3) and (4) are indeed the problems: you can remove the const qualification and add the volatile qualification all with a single cast.

You could replace the existing const_cast with a pair of casts, const_cast and volatile_cast, and prohibit case (2); then you could use either of them without the target type. However, then it's more difficult to know the type of the cast expression. To know whether a cast expression adds or removes qualification, you have to know what the type of the source expression is.

There's no reason you couldn't use a function template to get what you want:

template <typename T>
T* remove_const(const T* p) {
    return const_cast<T*>(p);
}

You could easily write similar functions for remove_volatile and for add_const and add_volatile, which are both implicit.

凉栀 2024-10-13 17:18:14

我认为詹姆斯·麦克内利斯已经谈到了重要原因。 const_cast既可以添加也可以删除常量/易失性。你并不总是清楚你想要什么。

如果我对 const foo 类型的参数调用 const_cast,这是否意味着我想将其设为非 const,或者添加 易失性?或者应该只是保留 const 限定符?如果我在类型(非常量)foo 的对象上调用它,它应该添加 const 吗?或者它应该假设我想删除 const-ness,并返回一个(非 const)foo 类型的对象?

另一个原因可能只是一致性。

我们有 static_cast(x)dynamic_cast(x)reinterpret_cast(x) 所以它没有类似模板的语法的 const_cast(x) 看起来很奇怪。

I think James McNellis already touched on the important reasons. const_castcan both add and remove constness/volatileness. It's not always clear what you want.

If I call const_cast on an argument of type const foo, does that mean I want to make it non-const, or add volatile to it? Or should it perhaps just keep the constqualifier? If I call it on an object of type (non-const) foo, should it add const? Or should it assume that I wanted to remove const-ness, and return an object of type (non-const) foo as well?

Another reason may simply be consistency.

We have static_cast<T>(x), dynamic_cast<T>(x), reinterpret_cast<T>(x) so it'd look odd to have a const_cast(x) without the template-like syntax.

身边 2024-10-13 17:18:14

主要原因是使用 const_cast 可以将 from 转换

Foo * const * volatile * * 

Foo * * * volatile * const

目标类型真的很明显吗?

The main reason is that using const_cast you can cast from

Foo * const * volatile * * 

to

Foo * * * volatile * const

Is it really obvious what the destination type is?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文