switch 语句条件中同时具有模板和非模板转换运算符的类

2024-03-13

问题最初出现在这个问题 https://stackoverflow.com/questions/25046418/internal-compiler-error-templated-conversion-operator-in-switch-expression。考虑以下代码:

class Var
{
public:

    operator int () const
    { return 0; }

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

};

int main()
{
    Var v;
    switch (v)
    { }
}

如果没有operator int() const { return 0; },g++ 和 clangreject https://stackoverflow.com/a/25046529/2756719代码。

然而,上面的代码,与operator int(), is accepted http://coliru.stacked-crooked.com/a/fd275beb734f3763通过 clang 但是rejected http://coliru.stacked-crooked.com/a/16a7feed152068f1通过 g++ 出现以下错误:

main.cpp:17:14: error: default type conversion can't deduce template argument for 'template<class T> Var::operator T() const'
     switch (v)
              ^

哪个编译器是正确的?


我相信clang这里是正确的。

我们可以从C++ 标准草案 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf部分6.4.2 switch 语句这涉及到上下文隐式转换。段落2说(*强调我的未来):

条件必须是整型、枚举类型或类 类型。如果是类类型,则条件是上下文隐含地 转换(第 4 条)为整数或枚举类型。

我们可以看到我们需要使用的部分是4 标准换算和段落5涵盖这些情况,它说:

某些语言结构需要转换为具有 1 的值 适合构造的一组指定类型。一个 在这样的上下文中出现的类类型 E 的表达式 e 被认为是上下文隐式转换到指定类型 T 并且是 格式良好当且仅当 e 可以隐式转换为类型 T 确定如下:E搜索转换函数 其返回类型是 cv T 或对 cv T 的引用,以便允许 T 通过上下文。应该恰好有一个这样的 T。

这不参考部分8.5它允许通过专门参考部分来进行重载解析13.3如果不允许重载解析,我们就不能使用:

template <typename T>
operator T () const

因此没有任何歧义。

请注意,这与段落不同4其中涵盖布尔转换在以下情况下if, while等等...并说(强调我的):

某些语言结构要求将表达式转换为 一个布尔值。在这样的上下文中出现的表达式 e 被称为 根据上下文转换为 bool 并且格式正确当且仅当 声明 bool t(e);是格式良好的,对于一些临时发明的 变量 t (8.5)。

它特别允许重载解析并直接引用部分13.3其中涵盖了这一点。这是有道理的,因为我们有特定的目的地类型bool转换为我们没有的switch case.

Why

我们可以通过查看来解决这个问题N3323:调整某些 C++ 上下文转换的提案,v3 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf它涵盖了这个问题。引用整篇论文是很困难的,所以我将尝试引用足够的上下文。它说:

C++ 表达式出现的上下文通常会影响 表达式被评估,因此可能对 表达式以确保这样的评估是可能的。 [...]

在四种情况下,FDIS (N3290) 使用不同的语言来指定 类似的上下文相关转换。在这四种情况下,当 操作数是类类型,该类型必须有一个“单个非显式 转换函数”到合适的(特定于上下文的)类型。 [...]

包括:

[stmt.switch]/2:“条件必须是整型、枚举 类型,或单个非显式转换的类类型 存在积分或枚举类型的函数(12.3)。”

并说:

在本文中引用的四种情况中的主要问题 简介,似乎在于他们共同的帮助但非常严格 将类限制为只有一个转换运算符的要求 [...]

另一个问题是当前限定词“single”的范围。 措辞。类中必须只有一个转换函数, 或者可以有多个,只要其中一个适合 语境?

目前的语言在这一点上似乎还不清楚。也是 不清楚是否有一个转换运算符产生对某个对象的引用 适当的类型是适当的转换运算符。 (一个关于 这一点已于 2011 年 2 月 21 日发布到核心反射器,但已 截至撰写本文时尚未得到答复。)当前的编译器实践似乎 承认这样的运营商,但目前的语言似乎不这么认为。

并建议:

为了解决所有这些问题,我们建议使用经过验证的 方法以术语上下文转换为 bool 为代表 定义在 [conv]/3 中。因此,我们建议适度补充 [conv]/3 定义到其他指定类型的上下文转换,以及 然后诉诸这个新定义。

新语言如下;

某些其他语言结构需要类似的转换,但要转换为 具有适合于的一组指定类型之一的值 构造。类类型 E 的表达式 e 出现在这样的上下文中 据说会根据上下文隐式转换为指定类型 T 当且仅当 e 可以隐式转换为 a 时,并且是格式良好的 类型T确定如下:搜索E进行转换 返回类型为 cv T 或对 cv T 的引用的函数,使得 T 是上下文所允许的。应该恰好有一个这样的 T。

Note N3486:C++ 编辑报告,2012 年 10 月 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3486.html向我们展示何时N3323已纳入标准草案。

Update

Filed a 海湾合作委员会错误报告 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62110.

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

switch 语句条件中同时具有模板和非模板转换运算符的类 的相关文章

随机推荐