简体   繁体   English

gcc7中的枚举和三元奇怪行为

[英]Enums and ternary strange behavior in gcc7

We are now testing compiling some Qt code under QtCreator with the newer gcc 7.3 available in Ubuntu 18 (we were previously using gcc 4.9.3 under Ubuntu 16). 现在,我们正在测试使用Ubuntu 18中提供的较新gcc 7.3在QtCreator下编译一些Qt代码(我们以前在Ubuntu 16下使用gcc 4.9.3)。

Qt provides an enum thus: Qt提供了一个enum因此:

enum CheckState {
    Unchecked,
    PartiallyChecked,
    Checked
};

Now, when we use the ternary operator with this: 现在,当我们将三元运算符与此一起使用时:

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

then gcc complains (with a warning, but we treat warnings as errors): 然后gcc抱怨(带有警告,但我们将警告视为错误):

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

We can get around the issue with: 我们可以通过以下方法解决此问题:

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

but I'm not sure why that should be necessary. 但我不确定为什么必须这样做。

Since these are coming from exactly the same enum , they should be the same type, no? 由于它们来自完全相同的enum ,因此它们应该是相同的类型,不是吗? I know that there are potential issues where the two possible values are different types, but I can't understand why this type casting needs to be done in this case. 我知道这两个可能的值是不同类型存在潜在的问题,但是我不明白为什么在这种情况下需要进行这种类型转换。

The values are {0, 1, 2} from the enum and I would have thought the exact same type negated any possibility for conversion. 值是来自enum {0, 1, 2} ,我认为完全相同的类型会排除转换的可能性。

The only possibility I can think of is the fact that the zero value of the enumeration is being treated as unsigned for some reason. 我能想到的唯一可能性是,由于某种原因,枚举的零值被视为无符号。

In lieu of an MCVE I am assuming the context is something like: 代替MCVE,我假设上下文类似于:

struct S
{
    S(int);
    S(unsigned int);
};

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

which produces warning in gcc 7.3 : 在gcc 7.3中产生警告

warning: passing Qt::CheckState chooses int over unsigned int [-Wsign-promo] 警告:传递Qt::CheckState选择int而非unsigned int [-Wsign-promo]


The warning relates to the implicit conversion of value of type enum CheckState to integer. 该警告与将enum CheckState类型的值隐式转换为整数有关。 There is valid implicit conversion to both int and unsigned int , and overload resolution selects int . intunsigned int都有有效的隐式转换,并且重载决议选择int

Apparently the rationale for the warning is that some older versions of gcc selected unsigned int in this scenario , but gcc 7 follows the Standard and selects int . 显然,发出警告的理由是,在这种情况下,某些旧版本的gcc选择了unsigned int ,但gcc 7遵循了Standard并选择了int

Your fix works because the second and third operands are brought to a common type of int before overload resolution occurs (it is not anything to do with which enumerator you chose). 您的修复之所以有效,是因为在发生重载解析之前,第二个和第三个操作数被带到一个普通的int类型(这与您选择的枚举数无关)。

Perhaps an appropriate fix would be to apply static_cast<int> to the whole conditional, not just one operand. 也许适当的解决方法是将static_cast<int>应用于整个条件,而不仅仅是一个操作数。

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

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