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

标签 c++ c++11 language-lawyer implicit-conversion c++14

问题最初出现在 this question .考虑以下代码:

class Var
{
public:

    operator int () const
    { return 0; }

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

};

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

没有操作符 int() const { return 0; },g++ 和 clang reject代码。

但是,上面的代码,带有 operator int(),是 accepted通过铿锵但rejected通过 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 在这里是正确的。

我们可以从 draft C++ standard 看到6.4.2switch 语句 这涉及 上下文隐式转换。第 2 段说(*强调我的 future ):

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.

我们可以看到我们需要使用的部分是 4 Standard Conversions 并且段落 5 涵盖了这些情况,它说:

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.

这不引用第 8.5 节,该节允许通过专门引用第 13.3 节来进行重载解析,而不允许我们无法使用的重载解析:

template <typename T>
operator T () const

因此没有歧义。

请注意,这与第 4 段不同,它涵盖了 ifwhile 等上下文中的 bool 转换。 .. 并说(强调我的):

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).

它特别允许重载解决方案,并直接引用涵盖此内容的 13.3 部分。这是有道理的,因为我们有一个特定的目标类型 bool 可以转换为我们在 switch 情况下没有的。

为什么

我们可以通过查看 N3323: A Proposal to Tweak Certain C++ Contextual Conversions, v3 来解决这个问题。它涵盖了这个问题。引用整篇论文会很困难,所以我将尝试引用足够多的上下文。它说:

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. [...]

包括:

[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).”

然后说:

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.

并提议:

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.

新语言如下;

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.

注意 N3486: C++ Editor's Report, October 2012向我们展示了 N3323 何时被纳入标准草案。

更新

提交了 gcc bug report .

关于c++ - switch 语句条件下同时具有模板和非模板转换运算符的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25047109/

相关文章:

c++ - Boost 文件系统与 c++11 线程不兼容

c++ - 无法在 Eclipse 中解析符号 'cv'

c++ - 在 Visual C++ 2008 Express Ed 中查找多行

c++ - Live555 RTSPServer 对象销毁不当或库错误?

c++ - 如何通过流插入运算符调用成员函数?

c++ - 枚举位域和聚合初始化

c++ - 使用 GDI C++ 动画方 block

c++ - `auto && e` 在基于范围的 for 循环中做了什么?

c++ - 具有可变参数模板和 va_args 的 function_traits

c++ - 为什么赋值表达式中的重叠必须是精确的并且对象必须具有相同的类型,这是什么意思?