为什么:
public class Addition {
public static void main() {
int a = 0;
double b = 1.0;
a = a + b;
System.out.println(a);
}
}
Run Code Online (Sandbox Code Playgroud)
不编译但是:
public class Addition {
public static void main() {
int a = 0;
double b = 1.0;
a += b;
System.out.println(a);
}
}
Run Code Online (Sandbox Code Playgroud)
编译.
假设你有这个:
struct Foo {
Foo(unsigned int x) : x(x) {}
unsigned int x;
};
int main() {
Foo f = Foo(-1); // how to get a compiler error here?
std::cout << f.x << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
是否有可能阻止隐式转换?
我能想到的唯一方法是explicilty提供一个构造函数,int如果int是负数,则会产生并产生某种运行时错误,但如果我为此得到编译器错误会更好.
我几乎可以肯定,有一个重复,但我能找到的最接近的是这个问题,而不是为什么允许隐式转换.
我对C++ 11和pre C++ 11解决方案感兴趣,最好是两者兼容.
例如,我有以下代码:
let numberOfBlocks = 3
let blockWidth = SKSpriteNode(imageNamed: "image.png").size.width
let padding = 20.0
let offsetX : Float = (self.frame.size.width - (blockWidth * numberOfBlocks + padding * (numberOfBlocks-1))) / 2
Run Code Online (Sandbox Code Playgroud)
我收到了错误:
'Double'不能转换为'UInt8'
有没有办法隐式转换数据类型(可能只对原始数据类型)?
编辑:
我知道如何通过使用Iducool建议的特定类型的构造函数来进行显式转换.但这对我的问题没什么大帮助,因为我们甚至不知道在哪里添加转换.我简化了我在游乐场的表达:

问题出在"填充"变量,错误信息是
'Double'不能转换为'UInt8'.
所以我做了转换:

那么现在的问题是"blockWidth"变量.
我再次添加了转换:

错误信息是:
类型'UInt8'不符合协议'FloatLiteralCovertible'
最终的工作表达式是:

它简单快捷吗?我不这么认为.
我的班级明确转换为bool:
struct T {
explicit operator bool() const { return true; }
};
Run Code Online (Sandbox Code Playgroud)
我有一个例子:
T t;
Run Code Online (Sandbox Code Playgroud)
要将它分配给类型的变量bool,我需要编写一个强制转换:
bool b = static_cast<bool>(t);
bool b = bool(t);
bool b(t); // converting initialiser
bool b{static_cast<bool>(t)};
Run Code Online (Sandbox Code Playgroud)
我知道我可以在没有强制转换的条件下直接使用我的类型,尽管有explicit限定符:
if (t)
/* statement */;
Run Code Online (Sandbox Code Playgroud)
我还可以t在bool没有演员阵容的情况下使用?
当我从一个整数(例如1-2.0)中减去一个浮点数时,Python会进行隐式类型转换(我认为).但是当我使用魔术方法调用我认为是相同的操作时__sub__,它突然不再存在了.
我在这里错过了什么?当我为自己的类重载运算符时,除了明确地将输入转换为我需要的任何类型之外,还有其他方法吗?
a=1
a.__sub__(2.)
# returns NotImplemented
a.__rsub__(2.)
# returns NotImplemented
# yet, of course:
a-2.
# returns -1.0
Run Code Online (Sandbox Code Playgroud) 我有以下C代码工作:
int ex(unsigned int x) {
int mask = 0x55555555;
int a = ((x >> 0) & mask );
return a + ((x >> 1) & mask );
}
Run Code Online (Sandbox Code Playgroud)
但是,当我将其扩展到此时,我得到了不同的结果:
int ex(unsigned int x) {
int mask = 0x55555555;
int a = ((x >> 0) & mask );
int b = ((x >> 1) & mask );
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
造成这种差异的原因是什么?
编辑:注意,我正在为32位编译.
问题最初出现在这个问题上.请考虑以下代码:
class Var
{
public:
operator int () const
{ return 0; }
template <typename T>
operator T () const
{ return T(); }
};
int main()
{
Var v;
switch (v)
{ }
}
Run Code Online (Sandbox Code Playgroud)
没有operator int() const { return 0; },g ++和clang都会拒绝代码.
然而,上面的代码,与所述operator int()被接受由铛但拒绝由g ++与以下错误:
main.cpp:17:14: error: default type conversion can't deduce template argument for 'template<class T> Var::operator T() const'
switch (v)
^
Run Code Online (Sandbox Code Playgroud)
哪个编译器正确?
struct A{
operator char() const{ return 'a'; }
operator int() const{ return 10; }
};
struct B {
void operator<< (int) { }
};
int main()
{
A a;
B b;
b << a;
}
Run Code Online (Sandbox Code Playgroud)
ato 的转换int可以是via,a.operator char()然后是整数提升,也可以是a.operator int()身份转换(即根本没有转换).标准说(§13.3.3.1[over.best.ics]/p10,脚注省略,加粗我的;所有引用均来自N3936):
如果存在几个不同的转换序列,每个转换序列将参数转换为参数类型,则与参数相关联的隐式转换序列被定义为指定为模糊转换序列的唯一转换序列.为了按照13.3.3.2中的描述对隐式转换序列进行排序,模糊转换序列被视为用户定义的序列,与任何其他用户定义的转换序列无法区分.如果选择使用模糊转换序列的函数作为最佳可行函数,则调用将是错误的,因为调用中的一个参数的转换是不明确的.
在这里,B::operator<<(int)是唯一可行的候选者 - 因此是最好的可行候选者,即使参数的转换序列是不明确的转换序列.然后,根据粗体句子,调用应该是格式错误的,因为"调用中的一个参数的转换是模糊的".
然而,我测试的编译器(g ++,clang和MSVC)实际上没有报告错误,这是有道理的,因为在通过重载决定选择调用函数之后,函数的"参数(8.3.5)应该被初始化(8.5,12.8) ,12.1)及其对应的参数"(§5.2.2[expr.call]/p4).这个初始化是复制初始化(§8.5[dcl.init]/p15),根据§8.5[dcl.init]/p17,导致新一轮的重载决策,以确定要使用的转换函数:
初始化器的语义如下.的目标类型 是对象或引用的类型被初始化和 源类型是初始化表达式的类型.如果初始化程序不是单个(可能带括号的)表达式,则不定义源类型.
- [...]
- 如果目标类型是(可能是cv限定的)类类型:[...]
- 否则,如果源类型是(可能是cv限定的)类类型,则考虑转换函数.列举了适用的转换函数(13.3.1.5),并通过重载决策(13.3)选择最佳函数.调用如此选择的用户定义转换以将初始化表达式转换为正在初始化的对象.如果转换不能完成或不明确,则初始化是错误的.
- [...] …
请考虑以下代码段:
int i = 99999999;
byte b = 99;
short s = 9999;
Integer ii = Integer.valueOf(9); // should be within cache
System.out.println(new Integer(i) == i); // "true"
System.out.println(new Integer(b) == b); // "true"
System.out.println(new Integer(s) == s); // "true"
System.out.println(new Integer(ii) == ii); // "false"
Run Code Online (Sandbox Code Playgroud)
很明显为什么最后一行总是打印出来"false":我们正在使用==引用标识比较,而new对象永远不会是==已经存在的对象.
问题是前三行:那些比较保证在原语上int,Integer自动取消装箱?是否存在基元将被自动装箱的情况,并且执行参考标识比较?(那就是全部false!)
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
Run Code Online (Sandbox Code Playgroud)
不编译: 'return': cannot convert from 'std::optional<int>' to 'bool'
咨询参考我本来想找到一个解释,但我读了它应该没问题。
每当在不接受该类型但接受其他类型 T2 的上下文中使用某种类型 T1 的表达式时,就会执行隐式转换;特别是:
- 当调用以 T2 为参数声明的函数时,将表达式用作参数时;
- 当表达式用作操作数时,运算符需要 T2;
- 初始化 T2 类型的新对象时,包括返回 T2 的函数中的 return 语句;
- 当表达式用于 switch 语句时(T2 是整型);
- 当表达式用于 if 语句或循环时(T2 是 bool)。