警告:缩小转换C ++ 11 [英] warning: narrowing conversion C++11

查看:198
本文介绍了警告:缩小转换C ++ 11的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

g ++ 4.9.0
-O2 -std = c ++ 11

g++ 4.9.0 -O2 -std=c++11

template<class T>
struct vec3 {
    T x, y, z;
    vec3() = default;
    vec3(const vec3<T> &other) = default;
    vec3(T xx, T yy, T zz) { x = xx; y = yy; z = zz; }
    vec3<T> operator-(const vec3<T> &other) { 
      return vec3<T>{ x - other.x, y - other.y, z - other.z }; 
    }
};

int main() {
    vec3<char> pos{ 0, 0, 0 };
    vec3<char> newPos{ 0, 0, 0 };
    auto p = pos - newPos;

    return 0;
}

我收到警告:

!!warning: narrowing conversion of ‘(((int)((vec3<char>*)this)->vec3<char>::x) - ((int)other.vec3<char>::x))’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

但是如果我用(...) insted {...} 运算符 - 函数中,警告消失。为什么?

But if I do it with (...) insted of {...} inside the operator- function the warning disappears. Why?

推荐答案

首先,为什么要缩小?这来自§5/ 10:

First, why narrowing? That comes from §5/10:


许多希望算术或枚举类型的操作数导致转换和产量结果类型的类似办法。目的是产生一个共同的类型,这也是结果的类型。这种模式称为通常的算术转换,定义如下:

- [..]

- 否则,将对两个操作数执行整数促销(4.5)。

— Otherwise, the integral promotions (4.5) shall be performed on both operands.

在4.5 / 1中定义:

where the integral promotion is defined in 4.5/1:


bool , char16_t char32_t wchar_t rank(4.13)小于 int 的等级可以转换为 int 类型的prvalue $ c> int 可以表示源类型的所有值;否则,源prvalue可以转换为 unsigned int 的prvalue。

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

在我们的例子中,我们有 decltype(char + char) int ,因为 char 的转换排名小于 int ,因此在调用前都被提升为 int 运算符+ 。现在,我们有 int ,我们传递给一个构造函数,该构造函数需要 char 。按照定义(§8.5.4/ 7,具体7.4):

In our case then, we have decltype(char + char) is int because char's conversion rank less than int so both are promoted to int before the call to operator+. Now, we have ints that we're passing to a constructor that takes chars. By definition (§8.5.4/7, specifically 7.4):


A narrowing conversion is an implicit conversion

(7.4) - 从整数类型或无范围的枚举类型到无法表示原始类型的所有值的整数类型,除非源是常量表达式其整数促销之后的值将适合目标类型。

(7.4) — from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

它明确禁止在列表初始化,具体根据§8.5.4 / 3(强调我的,看下面实际上是指我刚刚复制的上面):

which is explicitly prohibited in list-initialization specifically as per §8.5.4/3 (emphasis mine, the "see below" actually refers to what I just copied above):


列表初始化对象或 T 的引用定义如下

- [..]

- 否则,如果 T 是类类型,则会考虑构造函数。适用的构造函数被枚举,并且通过重载分辨率(13.3,13.3.1.7)选择最好的构造函数。 如果要转换任何参数时需要缩小转换(请参阅下文),程序会显示错误。 [...]

— Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed. [...]

这是为什么你的 vec3< T> {int,int,int} / code>给您一个警告:程序是不成形的,因为整数促销需要缩小所有表达式的转换。现在,关于不合格的声明特别出现在列表初始化的上下文中。这就是为什么如果你初始化你的向量没有 {} s ,你不会看到这个警告:

This is why your vec3<T>{int, int, int} gives you a warning: the program is ill-formed due to integer promotion requiring a narrowing conversion on all the expressions. Now, the statement about "ill-formed" specifically arises only in the context of list-initialization. This is why if you initialize your vector without {}s, you do not see that warning:

vec3<T> operator-(const vec3<T> &other) { 
    // totally OK: implicit conversion from int --> char is allowed here
    return vec3<T>( x - other.x, y - other.y, z - other.z );
}

至于解决这个问题 - 只是调用没有列表初始化的构造函数最简单的解决方案。或者,您可以继续使用列表初始化,只需为您的构造函数模板:

As to solving this problem - just calling the constructor without list-initialization is probably the simplest solution. Alternatively, you can continue to use list-initialization and just template your constructor:

template <typename A, typename B, typename C>
vec3(A xx, B yy, C zz)
: x(xx) // note these all have to be ()s and not {}s for the same reason
, y(yy)
, z(yy)
{ } 

这篇关于警告:缩小转换C ++ 11的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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