Igo*_*gor 5 c++ gcc type-conversion implicit-conversion c++11
我有以下代码:
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
}
Run Code Online (Sandbox Code Playgroud)
当我在 gcc 上编译它(在 7.3.0 和 8.2.0 上测试)时,-Wsign-conversion
我收到“警告:从‘long unsigned int’转换为‘long int’可能会改变结果的符号”。如果y
有 type long unsigned int
,则没有警告。此外,当我明确调用时y.get()
也没有警告:
std::cout << (x + y.get()); // this is ok
Run Code Online (Sandbox Code Playgroud)
为什么会出现这种情况呢?使用用户定义的转换时,是否有一些不能使用的指针算术特殊规则?
(感谢@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';
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 8.2.0,我们得到:
<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
Run Code Online (Sandbox Code Playgroud)
在链接中,您将看到如何:
因此,这肯定是一些关于标准合规性的极端情况。
现在,我确信有一个复杂的技术解释说明了为什么您只在这些流语句的第三个上收到错误。但我认为从实际使用的角度来看这并不重要。如果您坚持只向指针添加正确的整数 - 就像您对.get()
语句所做的那样 - 您不会收到该警告。
您看,您正在尝试将用户定义的类型添加到指针 - 这通常没有多大意义。确实,您的结构可以转换为整数,但是依赖于隐式进行的这种转换会让您面临诸如选择转换其他操作数或您未考虑的其他转换路径之类的事情。更重要的是,在这些情况下,您可能会“遇到”标准中有关隐式转换何时合法的一些深奥条款,编译器可能会或可能不会完全正确地实现这些条款(请参阅@cppcleaner的评论)。
因此,只需在您的代码中使用x + y3.get()
,您就不必担心这些深奥的极端情况。
我在这个答案中就使用空字符串的索引 0 提出了类似的论点(是的,就是这样)。
归档时间: |
|
查看次数: |
2945 次 |
最近记录: |