`a 的类型是什么?乙:丙`?

2024-02-18

假设我们有

template <typename T>
struct Foo
{};

and

struct Bar
{
    template <typename T>
    operator Foo<T>() const { return Foo<T>(); }
};

and

template <typename T>
Foo<T> Baz(T const&) { return Foo<T>(); }

Then, true ? Bar() : Baz(some_expr_of_type_double)有类型Foo<double>因为Bar可转换为Foo<double>。这个技巧用于查询类型some_expr_of_type_double而不对其进行评估。

确定类型的规则是什么a ? b : c?我很感激该标准的相关部分(我没有副本)。是否有超过“typeof(b)必须可转换为typeof(c)或者反之亦然,明确地”?


以下是相关规范:

5.16 条件运算符[expr.cond]

  1. 条件表达式组 右到左。第一个表达 隐式转换为 bool (第 4 条)。对其进行评估,如果 这是真的,结果 条件表达式是值 的第二个表达式,否则 也就是第三个表达式。全部 第一个表达式的副作用 除了破坏 临时(12.2)发生在 第二个或第三个表达式是 评价。只有第二个之一 并对第三个表达式进行求值。

  2. 如果第二个或第三个操作数的类型(可能是 cv 限定的)void,则左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换为对第二个和第三个操作数执行,并且以下之一应成立:

    — 第二个或第三个操作数(但不是两者)是一个 throw 表达式 (15.1);结果是另一个的类型并且是右值。

    — 第二个和第三个操作数的类型均为 void;结果是 void 类型并且是右值。

    [注意:这包括两个操作数都是 throw 表达式的情况。 ]

  3. 否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是 cv 限定的)类类型,则尝试将其中每个操作数转换为另一个操作数的类型。判断T1类型的操作数表达式E1是否可以转换为匹配T2类型的操作数表达式E2的过程定义如下:

    3.a:如果 E2 是左值:如果 E1 可以隐式转换(第 4 条)到“对 T2 的引用”类型,则 E1 可以转换为匹配 E2,但要遵守转换中引用必须直接绑定的约束( 8.5.3) 至 E1。

    3.b:如果E2是右值,或者上面的转换无法完成:

    3.b.1:如果E1和E2具有类类型,并且底层类类型相同或者一个是另一个的基类:如果T2的类与以下类型相同,则E1可以转换为匹配E2,或者 T1 类的基类,并且 T2 的 cv 资格与 T1 的 cv 资格相同,或者比 T1 的 cv 资格更高。如果应用转换,E1 将更改为 T2 类型的右值,该右值仍引用原始源类对象(或其适当的子对象)。 (注:即不进行复制。)

    3.b.2:否则(即,如果 E1 或 E2 具有非类类型,或者它们都具有类类型,但底层类不相同或者其中一个类不是另一个的基类):E1 可以转换为如果 E1 可以隐式转换为表达式 E2 在 E2 转换为右值时所具有的类型(或者如果 E2 是右值,则为它所具有的类型),则匹配 E2。

    使用该过程,确定是否可以将第二操作数转换为与第三操作数匹配,以及是否可以将第三操作数转换为与第二操作数匹配。如果两者都可以转换,或者其中之一可以转换但转换不明确,则程序格式错误。如果两者都不能转换,则操作数保持不变,并按如下所述执行进一步检查。如果恰好可以进行一次转换,则该转换将应用于所选操作数,并且在本节的其余部分中使用转换后的操作数代替原始操作数。

  4. 如果第二个和第三个操作数是左值并且具有相同的类型,则结果就是该类型并且是左值。

  5. 否则,结果是右值。如果第二个和第三个操作数没有相同的类型,并且其中一个具有(可能是 cv 限定的)类类型,则使用重载决策来确定要应用于操作数的转换(如果有)(13.3.1.2、13.6) 。如果重载决策失败,则程序格式错误。否则,应用由此确定的转换,并且在本节的其余部分中使用转换后的操作数代替原始操作数。

  6. 对第二个和第三个操作数执行左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换。进行这些转换后,应满足以下条件之一:

    6.a:第二个和第三个操作数具有相同的类型;结果就是这种类型。

    6.b:第二和第三操作数具有算术或枚举类型;执行通常的算术转换以使它们成为公共类型,并且结果就是该类型。

    6.c:第二、第三操作数为指针类型,或者一个为指针类型,另一个为空指针常量;执行指针转换(4.10)和限定转换(4.4)以将它们转换为复合指针类型(5.9)。结果是复合指针类型。

    6.d:第二个和第三个操作数具有指向成员类型的指针,或者一个具有指向成员类型的指针,另一个是空指针常量;执行指向成员转换 (4.11) 和限定转换 (4.4) 的指针以将它们转换为公共类型,其 cv 限定应与第二个或第三个操作数的 cv 限定相匹配。结果是普通类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

`a 的类型是什么?乙:丙`? 的相关文章

随机推荐