在switch语句的条件中具有模板和非模板转换运算符的类 [英] Classes with both template and non-template conversion operators in the condition of switch statement

查看:166
本文介绍了在switch语句的条件中具有模板和非模板转换运算符的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题最初出现在此问题中。考虑下面的代码:

  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 ++和clang 拒绝代码。



但是,上面的代码和运算符int()已接受,但由g ++ 拒绝,但发生以下错误:

  main.cpp:17:14:error:默认类型转换无法推导'template< class T& Var :: operator T()const'
switch(v)
^

我认为 clang 在这里是正确的。



我们可以从切换语句这涉及到上下文隐式转换 / em>。第 2段说(*强调我的进度):


条件应为整数类型,枚举类型,或类
类型。如果是类类型,条件是上下文隐式
转换(第4条)
为整数或枚举类型。



b $ b

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


某些语言结构需要转换为一个值
的一组指定的类型构建体。在这种上下文中出现的类类型E的
表达式e被认为是
上下文隐式转换为指定类型T,并且是
形式良好if和只有当e可以隐式转换为类型T
,其确定如下:E搜索转换函数
,其返回类型为cv T或引用cv T,以使T允许
由上下文。 $ <
通过特别参考 13.3 部分而不允许重载解决,我们不能使用:

  template< typename T> 
operator T()const

因此没有歧义。



请注意,这不同于如果 的上下文中的 bool转换 表达式转换为
a布尔值。出现在这样的上下文中的表达式e表示
被上下文地转换为bool,并且如果且仅当
是声明bool t(e); 格式正确,对于某些发明的临时
变量t(8.5)。


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



为什么



我们可以通过查看 N3323:调整某些C ++上下文转化的提议,v3 它涵盖了问题。很难引用整篇论文,所以我将尝试引用足够的上下文。它说:


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



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


并包括:


[stmt.switch] / 2:条件应该是整数类型,枚举
类型,或者类型类型的单个非显式转换
函数为整数或枚举类型存在(12.3)。


并说:



引言中引用的四个上下文中的每一个中的主要问题似乎在于它们常见的有帮助但非常严格的
要求,将一个类限制为只有一个转换运算符。 。]



另一个问题是当前
中的限定词single的范围。在类中必须有一个单一的转换函数,
或可能有几个,只要一个单一的转换函数适合于
上下文?



目前的语言在这一点上似乎不太清楚。它也是
不清楚产生对
适当类型的引用的转换运算符是否是适当的转换运算符。 (关于
这一点的问题在2011-02-21发布到Core反射器,但是有
在撰写本文时没有回答。)当前编译器实践似乎
允许这样的运算符,但目前的语言似乎不是。


并建议:


为了解决所有这些问题,我们建议使用由上下文转换为bool的术语表示的已证明的
方法作为在[conv] / 3中定义的
。因此,我们建议对
[conv] / 3进行适度的增加,以定义到其他指定类型的上下文转换,然后
然后吸引这个新定义。


且新语言如下:


某些其他语言结构需要类似的转换,到具有适合于
结构的指定的一组类型之一的
值。出现在这种上下文
中的类型E的表达式e被称为上下文隐式地转换为指定类型T
,并且形式良好,如果且仅当e可以隐式地转换为
类型T,如下确定:E搜索转换
返回类型为cv T的函数或对cv T的引用,使得T
被上下文允许。正好有一个这样的T。


注意 N3486:C ++编辑报告,2012年10月向我们表明, N3323 已纳入草案更新



提交 gcc错误报告


The problem originally arose in this question. Consider the following code:

class Var
{
public:

    operator int () const
    { return 0; }

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

};

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

Without the operator int() const { return 0; }, both g++ and clang reject the code.

However, the above code, with the operator int(), is accepted by clang but rejected by g++ with the following error:

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

Which compiler is correct?

解决方案

I believe clang is correct here.

We can see from the draft C++ standard section 6.4.2 The switch statement that this involves a contextually implicit conversion. Paragraph 2 says (*emphasis mine going forward):

The condition shall be of integral type, enumeration type, or class type. If of class type, the condition is contextually implicitly converted (Clause 4) to an integral or enumeration type.

We can see the section we need to use is 4 Standard conversions and paragraph 5 covers these cases, it says:

Certain language constructs require conversion to a value having one of a specified set of types appropriate to the construct. An expression e of class type E appearing in such a context is said to be contextually implicitly converted to a specified type T and is well-formed if and only if e can be implicitly converted to a type T that is determined as follows: E is searched for conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context. There shall be exactly one such T.

This does not reference section 8.5 which allows for overload resolution by specifically referring to section 13.3 without allowing overload resolution we can not use:

template <typename T>
operator T () const

and therefore there is no ambiguity.

Note this is different from paragraph 4 which covers bool conversions in contexts of if, while etc... and says (emphasis mine):

Certain language constructs require that an expression be converted to a Boolean value. An expression e appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (8.5).

which specifically allows for overload resolution and refers directly to section 13.3 which covers this. It makes sense that it is allowed since we have a specific destination type bool to convert to which we don't have in the switch case.

Why

We can figure this out by going looking at N3323: A Proposal to Tweak Certain C++ Contextual Conversions, v3 it covers this issue. It would be hard to quote the whole paper so I will attempt to quote enough of the context. It says:

The context in which a C++ expression appears often influences how the expression is evaluated, and therefore may impose requirements on the expression to ensure such evaluation is possible. [...]

In four cases, the FDIS (N3290) uses different language to specify an analogous contextdependent conversion. In those four contexts, when an operand is of class type, that type must have a "single non-explicit conversion function" to a suitable (context-specific) type. [...]

and includes:

[stmt.switch]/2: "The condition shall be of integral type, enumeration type, or of a class type for which a single non-explicit conversion function to integral or enumeration type exists (12.3)."

and says:

The principal issue, in each of the four contexts cited in the Introduction, seems to lie in their common helpful but very strict requirement that limits a class to only one conversion operator [...]

Another concern is the scope of the qualifier "single" in the current wording. Must there be but a single conversion function in the class, or may there be several so long as a single one is appropriate to the context?

The current language seems unclear on this point. It is also unclear whether a conversion operator that produces a reference to an appropriate type is an appropriate conversion operator. (A question on this point was posted to the Core reflector on 2011-02-21, but has gone unanswered as of this writing.) Current compiler practice seems to admit such operators, but the current language seems not to.

and proposes:

To address all these concerns, we recommend instead to use the proven approach typified by the term contextually converted to bool as defined in [conv]/3. We therefore propose a modest addition to [conv]/3 to define contextual conversion to other specified types, and then appeal to this new definition.

and the new language would be as follows;

Certain other language constructs require similar conversion, but to a value having one of a specified set of types appropriate to the construct. An expression e of class type E appearing in such a context is said to be contextually implicitly converted to a specified type T and is well-formed if and only if e can be implicitly converted to a type T that is determined as follows: E is searched for conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context. There shall be exactly one such T.

Note N3486: C++ Editor's Report, October 2012 shows us when N3323 was incorporated in the draft standard.

Update

Filed a gcc bug report.

这篇关于在switch语句的条件中具有模板和非模板转换运算符的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆