gcc 奇怪的转换警告(<B>从"int"转换为"A::count_type {aka short unsigned int}"可能会改变其值)

gcc weird conversion warning (conversion to ‘A<B>::count_type {aka short unsigned int}’ from ‘int’ may alter its value)

本文关键字:int 转换 short aka type 改变 unsigned 警告 lt gcc count      更新时间:2023-10-16

我有以下使用模板的C++11代码:

struct Base{
    using count_type = unsigned short;
};
template<class T>
struct A : public Base{
    using count_type = A::count_type;
    // not works even if I comment this
    count_type add(T x){
        count_type sum = 5;
        sum += x.value(); 
        //sum += (count_type) x.value(); // not works even if I cast this, e.g.

        return sum;
    }
};
struct B{
    using count_type = A<B>::count_type;
    count_type value(){
        return 5; // not works even if I do:
        //return (count_type) 5;
        //return 5U;
    }
};
int main(int argc, char *argv[]){
    B b;
    A<B> a;
    a.add(b);
}

当我尝试用-Wconversion编译时,我收到了一条奇怪的错误消息:

$ g++ -std=c++11  -Wconversion x.cc
x.cc: In instantiation of ‘A<T>::count_type A<T>::add(T) [with T = B; A<T>::count_type = short unsigned int]’:
x.cc:29:9:   required from here
x.cc:11:7: warning: conversion to ‘A<B>::count_type {aka short unsigned int}’ from ‘int’ may alter its value [-Wconversion]
   sum += x.value();
       ^

为什么会发生这种情况?哪里没有int

如果有人修改我的问题,我将不胜感激。

注:clang未给出此警告。

sum += x.value();的意思(大致)是sum = sum + x.value();这里的RHS sum + x.value()将两个unsigned short值相加,生成一个int。将该int分配回unsigned short可以改变其值。

在我看来,这个警告不是特别有用,我建议关闭它,但如果你出于某种原因想保持它的启用状态,请在那里写一个演员阵容:

sum = (count_type) (sum + x.value());

sum = static_cast<count_type>(sum + x.value());

根据隐式提升,任何算术表达式(如sum = sum + x.value())都会经历一种称为常规算术转换的模式,该模式是标准§5中的相关部分:

--否则,应对两个操作数执行积分提升(4.5)。59然后,以下规则应适用于提升的操作数:

整体促销规定:

如果int可以表示源类型的所有值,则其整数转换秩(4.13)小于int的秩的除bool、char16_t、char32_t或wchar_t之外的整数类型的prvalue可以转换为类型int的prvalue;否则,源prvalue可以转换为unsigned int类型的prvalue。

因此,操作数被转换为int,然后返回到unsigned short。这是因为转换等级指定

有符号整数类型的秩应大于任何大小较小的有符号整数型的秩。

任何无符号整数类型的秩都应等于相应的有符号整数类型。