繁体   English   中英

是什么类型的? b:c`?

[英]What is the type of `a ? b : c`?

让我们说我们有

template <typename T>
struct Foo
{};

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

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

那么, true ? Bar() : Baz(some_expr_of_type_double) true ? Bar() : Baz(some_expr_of_type_double)类型为Foo<double>因为Bar可以转换为Foo<double> 此技巧用于在不some_expr_of_type_double进行评估的some_expr_of_type_double下查询some_expr_of_type_double的类型。

确定a ? b : c类型的规则a ? b : c a ? b : c 我很欣赏标准的相关部分(我没有副本)。 有没有“ typeof(b)必须可以转换为typeof(c) ,反之亦然,毫无疑问”?

这是相关规范:

5.16条件运算符[expr.cond]

  1. 条件表达式从右到左分组。 第一个表达式隐式转换为bool(第4节)。 它被评估,如果是,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值。 除了临时破坏(12.2)之外,第一个表达式的所有副作用都发生在评估第二个或第三个表达之前。 仅评估第二和第三表达式中的一个。

  2. 如果第二个或第三个操作数具有类型(可能是cv-qualified)void,则左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)标准转换是在第二和第三个操作数上执行,并且以下之一应该成立:

    - 第二个或第三个操作数(但不是两个)是一个throw-expression(15.1); 结果是另一个的类型,是一个右值。

    - 第二个和第三个操作数都有类型void; 结果是void类型,是一个rvalue。

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

  3. 否则,如果第二个和第三个操作数具有不同的类型,并且具有(可能是cv-qualified)类类型,则尝试将每个操作数转换为另一个操作数的类型。 确定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资格相同的cv资格或更高的资格。 如果应用转换,则将E1更改为类型T2的右值,该值仍然引用原始源类对象(或其相应的子对象)。 (注意:即没有复制。)

    3.b.2:否则(即,如果E1或E2具有非类型类型,或者它们都具有类类型但基础类不是相同的或一个是另一个的基类):E1可以转换为如果E2可以隐式转换为表达式E2,如果E2被转换为rvalue(或者它具有的类型,如果E2是rvalue),则匹配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资格应匹配第二个或第三个操作数的cvqualification。 结果是普通类型。

它不仅仅是(b)类型必须可转换为(c)类型。 这是一套复杂的规则,在5.16:2-6中列出; 关于一页长度。 有一些尝试和一堆关于左值与右值的东西。

你有一个C ++ 0x编译器吗? 在那种情况下, decltype(a ? b : c)可能? 但是不确定这是否正确处理引用。 任何人?

我很欣赏标准的相关部分(我没有副本)

您可以从WG21网站免费获取当前草稿

标准(您可以在这里找到的当前草案)在解释确切的打字程序时做了彻底的,如果不一定清楚的工作。 我得到的是表达式(BOOL?Y:Z):

它首先检查从Y到Z的隐式或显式转换类型。然后检查类似的基类,或者是否可以将Y类转换为Z.

当然,这个标准是难以消化的,我可能会非常偏离这里,但从我所读到的,突出的部分是我们总是尝试Y-> Z转换。 这将使我们相信结果也是Z型。这有趣的副作用是,如果我们放置X =(BOOL?Y:Z)并且存在Y-> X和Z-> X转换,但没有Y-> Z转换,那么程序就不正确了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM