【问题标题】:Enums and ternary strange behavior in gcc7gcc7中的枚举和三元奇怪行为
【发布时间】:2019-06-04 02:06:29
【问题描述】:

我们现在正在使用 Ubuntu 18 中可用的较新 gcc 7.3 在 QtCreator 下测试编译一些 Qt 代码(我们之前在 Ubuntu 16 下使用 gcc 4.9.3)。

Qt 提供了一个enum 因此:

enum CheckState {
    Unchecked,
    PartiallyChecked,
    Checked
};

现在,当我们使用三元运算符时:

QVariant MyClass::MyFunc(const QModelIndex &index, int role) const {
    return (someCondition ? Qt::Checked : Qt::Unchecked);
}

然后gcc 抱怨(带有警告,但我们将警告视为错误):

prog.cpp:999:99:
    error: passing ‘Qt::CheckState’ chooses ‘int’
        over ‘uint {aka unsigned int}’ [-Werror=sign-promo]

我们可以解决这个问题:

return (someCondition ? Qt::Checked : static_cast<int>(Qt::Unchecked));

但我不确定为什么需要这样做。

既然这些来自完全相同的enum,它们应该是相同的类型,不是吗?我知道两个可能的值是不同类型的潜在问题,但我不明白为什么在这种情况下需要进行这种类型转换。

这些值是来自enum{0, 1, 2},我认为完全相同类型否定了任何转换的可能性。

我能想到的唯一可能性是枚举的零值由于某种原因被视为无符号。

【问题讨论】:

    标签: c++ qt gcc enums


    【解决方案1】:

    代替 MCVE,我假设上下文类似于:

    struct S
    {
        S(int);
        S(unsigned int);
    };
    
    S foo()
    {
        return (1 ? Qt::Checked : Qt::Unchecked);
    }
    

    produces warning in gcc 7.3:

    警告:通过Qt::CheckState 选择int 而不是unsigned int [-Wsign-promo]


    警告与将 enum CheckState 类型的值隐式转换为整数有关。对intunsigned int 都有有效的隐式转换,并且重载决议选择int

    显然,警告的基本原理是在这种情况下,一些旧版本的 gcc 选择了unsigned int,但 gcc 7 遵循标准并选择了int

    您的修复工作有效,因为在重载解析发生之前,第二个和第三个操作数被带到了int 的常见类型(这与您选择的枚举数无关)。

    也许适当的解决方法是将static_cast&lt;int&gt; 应用于整个条件,而不仅仅是一个操作数。

    【讨论】:

    • MM,我想你可能是对的。我一直在尝试获得一个返回值为 int 和 unsigned int 的 MCVE,但没有出现故障。实际代码返回一个QVariant,它几乎肯定有许多类型的构造函数(doc.qt.io/qt-5/qvariant.html),包括QVariant(int val)QVariant(uint val)
    • 只是出于兴趣,您会认为这是一个错误吗?在我看来,如果值来自同一个枚举,编译器应该将它们视为不同的类型。
    • @paxdiablo 它们不被视为不同的类型。条件结果的类型为 enum CheckState ,警告来自将 enum CheckState 隐式转换为 QVariant 的尝试。如果您将代码更改为return Qt::Checked;,您可能会收到相同的警告
    • 正确。啊,我想我现在明白了。它实际上与三元无关,只是警告 gcc 更喜欢一种转换而不是另一种转换,这在逻辑上是在选择过程之后。删除任一构造函数可以解决问题(当然不是真正的 Qt 选项,这不是我们的代码)。投射我们返回的整个表达式也可以修复它,并允许我以我的强迫症倾向批准 PR :-) 感谢您的协助。
    • FWIW,我们选择了return static_cast&lt;int&gt;(1 ? Qt::Checked : Qt::Unchecked);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多