C++ 为什么我会收到Wsign转换警告?

C++ 为什么我会收到Wsign转换警告?,c++,c++11,gcc,type-conversion,implicit-conversion,C++,C++11,Gcc,Type Conversion,Implicit Conversion,我有以下代码: template <typename T> struct wrapper { T t; operator T() { return t; } T get() { return t; } }; int main() { int a[10]; int* x = a; wrapper<long unsigned int> y{2}; std::cout << (x + y); // warni

我有以下代码:

template <typename T>
struct wrapper {
    T t;
    operator T() { return t; }
    T get() { return t; }
};

int main() {
    int a[10];
    int* x = a;
    wrapper<long unsigned int> y{2};
    std::cout << (x + y); // warning
}
为什么会这样?在使用用户定义的转换时,是否有一些指针算法的特殊规则不能使用

似乎是编译器问题/错误 (感谢@liliscent纠正我之前在这里说的话)

首先,让我们为您提到的所有声明制作一张单张:

#include <iostream>

template <typename T>
struct wrapper {
    T t;
    operator T() const { return t; }
    T get() const { return t; }
};

int main() {
    int a[10];
    int* x { a } ;
    wrapper<long int> y1{2};
    wrapper<unsigned int> y2{2};
    wrapper<long unsigned int> y3{2};

    std::cout << (x + y1) << '\n';
    std::cout << (x + y2) << '\n';
    std::cout << (x + y3) << '\n'; // this triggers a warning
    std::cout << (x + y3.get()) << '\n';
}
#包括
模板
结构包装器{
T;
运算符T()常量{return T;}
T get()常量{return T;}
};
int main(){
INTA[10];
int*x{a};
包装y1{2};
包装y2{2};
包装y3{2};

std::cout注意,IIRC,指针算法仅为数组元素定义。对于
x+y
,执行重载解析,并使用内置的候选
T*运算符+(T*,std::ptrdiff\u T);
被选中。但是,GCC在生成警告时似乎忽略了这一点。@DanielLangr对,我对问题进行了编辑,因此
a
现在是数组类型。我担心这不会回答发布的问题。我完全理解这是答案的第二部分,第一部分会解释原因。所以答案是“这就是为什么;但是请做一些理智的事情,像这样。”但是没有第一部分,这不是答案。理解为什么会发生事情比“一个因为它发生而起作用的解决方案”更有价值@Angew:在某些情况下,理解为什么会发生某些事情是有价值的。在这种情况下,我认为不理解为什么会发生这些事情是有价值的(除非你是在探索GCC的行为,而不是编写C++)。但我会尝试稍微编辑以强调这一点。@Angew…但还是在答案中添加了第一部分。看起来clang并没有警告您-->错误。您应该通过
-Wsign conversion
来启用警告,或者
-Weverything
@einpoklum警告存在于clang 6.0中,而不是7.0中。可能是错误。
#include <iostream>

template <typename T>
struct wrapper {
    T t;
    operator T() const { return t; }
    T get() const { return t; }
};

int main() {
    int a[10];
    int* x { a } ;
    wrapper<long int> y1{2};
    wrapper<unsigned int> y2{2};
    wrapper<long unsigned int> y3{2};

    std::cout << (x + y1) << '\n';
    std::cout << (x + y2) << '\n';
    std::cout << (x + y3) << '\n'; // this triggers a warning
    std::cout << (x + y3.get()) << '\n';
}
<source>: In function 'int main()':
<source>:20:23: warning: conversion to 'long int' from 'long unsigned int' may change the sign of the result [-Wsign-conversion]
     std::cout << (x + y3) << '\n';
                       ^~
Compiler returned: 0