10

我放弃这个...

$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 应为指向多态类型 (10.3) 的指针或左值。

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

4

3 回答 3

9

那么,5.2.7中的所有要求应该一起遵守。你不能在 5.2.7/2 之后停下来开始编写可以满足“直到 5.2.7/2”的所有内容的代码。整个 5.2.7 定义了dynamic_cast.

多态性要求被挑出来,因为它是有条件的。当你使用dynamic_castfor upcasts 时,多态性要求不适用(实际上dynamic_cast相当于static_castin upcasts)。多态要求仅适用dynamic_cast于向下转换或交叉转换。

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

于 2010-11-17T10:39:27.733 回答
4

为了像您的示例一样进行向下转换,结构 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?
}

通过添加一个 virtual 使其具有多态性,该类启用了 RTTI,允许向下转换。

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


更新:

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

于 2010-11-17T10:52:08.497 回答
3

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

您可以这样说,因为 /2 对程序的操作数提出了要求dynamic_cast(请注意,“v 应为左值”的“shall”语言与“结果为左值”的“is”语言) . 与标准中的其他地方一样,表达要求并不一定意味着它是唯一的要求。其他条款可以说明额外的要求。在这种情况下,/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 没有“否则”(除非要说“否则,符合标准的编译器必须发出诊断”,但这是隐含的)

于 2010-11-17T10:54:47.583 回答