C++中显式类型转换的强制类型转换符号(C风格)和static_cast的多种解释

4

[expr.cast]的第4段(在撰写本文时可用的最新C++标准草案中)描述了C风格转换的行为,内容如下:

通过使用显式类型转换的强制转换符号,可以执行以下转换:

  • const_­cast
  • static_­cast
  • static_­cast 后跟 const_­cast
  • reinterpret_­cast
  • reinterpret_­cast 后跟 const_­cast

相同的语义限制和行为适用,但在以下情况下执行 static_­cast 时,即使基类不可访问,转换也是有效的:

  • 派生类类型的对象的指针或派生类类型的左值或右值可以明确转换为分别指向无歧义基类类型的指针或引用;
  • 派生类类型的成员指针可以明确转换为无歧义非虚基类类型的成员指针;
  • 无歧义非虚基类类型的对象指针、无歧义非虚基类类型的 glvalue 或无歧义非虚基类类型的成员指针可以明确转换为派生类类型的指针、引用或成员指针。

如果一个转换可以被解释为上述多种方式中的一种以上,则使用列表中首先出现的解释,即使由该解释产生的强制转换是非法的。 如果一个转换可以被解释为 static_­cast 后跟 const_­cast 的多种方式,则该转换是非法的。[...]

我的问题是如何将“一个转换被解释为一个static_castconst_cast的组合”?谢谢。

好的,但第一句话说:“[...]即使从该解释得出的强制转换不符合规范,也将使用列表中首先出现的解释。”使用static_cast进行模糊基类转换是不符合规范的,因此突出显示的句子不再必要。此外,突出显示的句子单独列出了一个更具体的情况:“static_­cast后跟const_­cast”。 - user42768
2
类似这样的:一个类具有两个用户定义的转换运算符,一个是转换为 int const **,另一个是转换为 int* const *。C 风格的强制转换为 int**演示 - Igor Tandetnik
1个回答

4

类似这样:

struct S {
    operator int const**() { return nullptr; }
    operator int *const*() { return nullptr; }
};

S s;
(int**)s;  // error: cannot cast from type 'S' to pointer type 'int **'

类似于 int const**int *const* 的类型可以成功转换。 演示


谢谢!对于reinterpret_cast后跟const_cast来说,这不是问题,因为reinterpret_cast可以自由地直接转换为与目标类型类似(或相同)的类型,但至少与源类型具有相同的cv限定符,然后让const_cast去除const属性,对吗?因此,"中间"类型不能有多个选项。 - user42768
reinterpret_cast 不使用转换运算符。它首先无法将非指针类型强制转换为指针类型。 - Igor Tandetnik
我有一个不同的例子在脑海中(https://wandbox.org/nojs/gcc-head/permlink/pJMBr70taUyQnIiN)。当需要一个`reinterpret_cast`后跟一个`const_cast`时,是因为目标类型比源类型“少cv限定符”(否则将选择`reinterpret_cast`,因为它在列表上更高)。因此,`reinterpret_cast`用于转换为类似于目标类型的类型,但至少与源类型“一样cv限定”。 - user42768
这是因为,正如您所说的那样,reinterpret_cast 不关心源类型是否隐式或显式可转换为目标类型。然后 const_cast 用于去除常量性。但是,如果我们有像 (int **) v 这样的东西,其中 v 的类型是 (const X **),那么 C 风格的强制转换可以解释为 const_cast<int **> (reinterpret_cast<const int * const *> (v))(也就是说,reinterpret_cast 可以添加一些更多的 constness)。但是这个选择没有可观察到的副作用,不像在您的例子中选择两个转换操作符那样。 - user42768
“@IgorTandetnik “在第一次转换中,它无法从非指针类型转换为指针类型。” 您肯定是指从类对象到指针的转换。” - curiousguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接