动态转换混乱

发布于 2024-10-03 02:34:31 字数 630 浏览 6 评论 0原文

我放弃这个了...

$5.2.7/2-“如果 T 是指针类型,则 v 应为指向的指针的右值 完整的类类型,结果是 T 类型的右值。如果 T 是 引用类型,v 应为左值 一个完整的类类型,以及 结果是该类型的左值 T 提到的。”

,下面的代码应该是格式良好的。

struct A{};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

但事实并非如此。所有编译器都抱怨dynamic_cast的操作数不是多态的

$5.2.7/6-否则,v 应为 指向 a 的指针或 a 的左值 多态类型(10.3)。

所以我的问题是 $5.2.7/2 是什么意思?为什么这里会出现 5.2.7/6 美元?

I give up on this...

$5.2.7/2- "If T is a pointer type, v
shall be an rvalue of a pointer to
complete class type, and the result is
an rvalue of type T. If T is a
reference type, v shall be an lvalue
of a complete class type, and the
result is an lvalue of the type
referred to by T."

In accordance with the above, the following code should be well-formed.

struct A{};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

But it is not. All compilers complain about the operand to dynamic_cast not being polymorphic in accordance with

$5.2.7/6- Otherwise, v shall be a
pointer to or an lvalue of a
polymorphic type (10.3).

So my question is what does $5.2.7/2 mean? Why does $5.2.7/6 kick in here?

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

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

发布评论

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

评论(3

来世叙缘 2024-10-10 02:34:31

那么,5.2.7 中的所有要求都应该一起遵守。您不能在 5.2.7/2 之后停止并开始编写据称满足“直到 5.2.7/2”的所有内容的代码。整个5.2.7定义了dynamic_cast的规范。

多态性需求被单独提出来,因为它是有条件的。当您使用dynamic_cast进行向上转换时,多态要求不适用(事实上,dynamic_cast相当于向上转换中的static_cast)。仅当您使用 dynamic_cast 进行向下转型或交叉转型时,多态要求才适用。

dynamic_cast 的规范是按顺序组织的,这意味着它首先处理更简单的情况,然后再处理更复杂的应用程序。您应该逐步阅读它,直到它涵盖您的具体情况。您沿着该路径阅读的所有内容都会累积适用,“否则”意味着:“如果我们尚未涵盖您的案例,则继续阅读”。

Well, all requirements in 5.2.7 should be observed together. You can't just stop after 5.2.7/2 and start writing code that supposedly satisfies everything "up to 5.2.7/2". The entire 5.2.7 defines the specification of dynamic_cast.

The polymorphic requirement is singled out because it is conditional. When you use dynamic_cast for upcasts, the polymorphic requirement does not apply (in fact, dynamic_cast is equivalent to static_cast in upcasts). The polymorphic requirement only applies when you use dynamic_cast for downcasts or crosscasts.

The specification of dynamic_cast is organized sequentially, meaning that it takes care of simpler cases first, and then proceeds to more complicated applications. You are supposed to read it step by step, until it covers your specific situation. Everything you read along that path applies cumulatively, And "otherwise" means: "if we haven't covered your case yet, then continue reading".

远山浅 2024-10-10 02:34:31

为了像您的示例中那样进行向下转型,结构 A 需要是多态的,并且具有 RTTI。下面是一个在某种程度上可行的调整版本:

struct A{virtual void f(){}};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   //B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

通过添加虚拟使其多态,为该类启用 RTTI,从而允许向下转型。

请注意,您的第二个示例无法工作 - 因为您将 pod (a) 转换为对 pod 的引用 - 这是不允许的。


更新:

您的代码在 5.2.7.5 下不允许,在 5.2.7.6 下也不允许。我的调整使其在5.2.7.6下工作

In order to do a downcast as in your example, Struct A needs to be polymorphic, and have RTTI. Here's an adjusted version that works, to a point:

struct A{virtual void f(){}};
struct B : A{};

int main(){
   B b;
   A a, &ar1 = b;

   B& rb1 = dynamic_cast<B&>(ar1);  // Does not $5.2.7/2 apply here?
   //B& rb2 = dynamic_cast<B&>(a);    // and also here?
}

By adding a virtual making it polymorphic, RTTI is enabled for the class, allowing downcasts.

Note that your second example cannot work - since you are casting a pod (a) to a reference to a pod - which is not allowed.


Update:

Your code is not allowed under 5.2.7.5 and is neither allowed under 5.2.7.6. My adjustment makes it work under 5.2.7.6

青丝拂面 2024-10-10 02:34:31

在这种情况下,“否则”是指“除非 5.2.7/5 中的条件适用”。

您可以看出这一点,因为 /2 对程序提出了有关 dynamic_cast 操作数的要求(请注意“v 应是左值”的“shall”语言与“结果是左值”)。与标准中的其他地方一样,表达需求并不一定意味着它是唯一需求。其他条款可以规定额外的要求。在这种情况下,/6 声明了一个仅适用于某些情况的额外要求,具体取决于 T 和 v 的静态类型。/3、/4、/5

告诉您有关结果,与/2中的要求完全一致。它们都没有以“否则”开头。所以对我来说,很明显它们没有形成从 /2 开始的“else if”链。

一些括号或其他东西可能会使这一点更清楚(即/6中的“否则”适用于/5中的“if”,而不适用于/2、/3或/4中的“if”)。但这不是房子的风格。

抛开其他不说,/5 中的“否则”在逻辑上不能有意义地适用于/2 中的条件。 /1 表示 T 必须是“完整类类型的指针或引用,或 cv void* ”。 /2 涵盖两种情况 - 指针类型和引用类型。这就是一切。 /2 没有“否则”(除非它说“否则,符合标准的编译器必须发出诊断”,但这是隐含的)

"Otherwise" in this case means, "unless the conditions in 5.2.7/5 apply".

You can tell this because /2 places a requirement on the program regarding the operand of the the dynamic_cast (note the "shall" language of "v shall be an lvalue" vs. the "is" language of "the result is an lvalue"). In common with other places in the standard, expressing a requirement doesn't necessarily mean that it's the only requirement. Other clauses can state extra requirements. In this case, /6 states an extra requirement that only applies in certain cases, depending on T and the static type of v.

/3, /4, /5 are telling you about the value of the result, and they're entirely consistent with the requirement in /2. None of them starts with "Otherwise". So to me it's fairly obvious that they do not form an "else if" chain starting at /2.

Some brackets or something might make this clearer (i.e. that the "otherwise" in /6 applies to the "if" in /5, and not to the "if" in /2, /3, or /4). But that's just not the house style.

Aside from anything else, the "otherwise" in /5 logically cannot meaningfully apply to the conditions in /2. /1 says that T must be "pointer or reference to complete class type, or cv void* ". /2 covers two cases - pointer types, and reference types. That's everything. There is no "otherwise" to /2 (unless it were to say "otherwise, a conforming compiler must issue a diagnostic", but that's implicit)

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