第一个操作数是常量表达式时的'?:'类型
Type of '?:' if the first operand is a constant expression
考虑以下代码:
void f(float x)
{
x * (true ? 1.f : 0.0);
}
根据C++标准[expr.cond],declval(bool) ? declval(float) : declval(double)
的类型是double
这是否意味着上述代码必须等效于:
void f(float x)
{
double(x) * 1.0;
}
或者,如果?:
的第一个操作数是编译时常数表达式,是否有允许优化的语句?
是的,这确实意味着上述代码是等效的。
使用RTTI,我们可以检查至少clang
和g++
都符合标准,并将d
(例如,double)作为该程序的输出:
#include <iostream>
#include <typeinfo>
int main() {
float x = 3.;
auto val = x * (true ? 1.f : 0.0);
std::cout << typeid(val).name() << std::endl;
}
以及使用C++11类型特征的替代方法
#include <iostream>
#include <typeinfo>
int main() {
float x = 3.;
auto val = x * (true ? 1.f : 0.0);
std::cout << std::boolalpha <<
std::is_same<decltype(val), double>::value << std::endl;
}
输出true
。
C++编译器可以根据自己的意愿进行优化,前提是它不会改变一致性程序的"可观察行为"(§1.9p1,即所谓的"好像"规则)。
例如,如果在给定的平台上,已知乘以1.0是一种没有陷阱的恒等式变换,那么实际上不需要执行乘法。(对于给定的体系结构,这可能是真的,也可能不是真的,因为将NaN值乘以1.0可能会陷阱。然而,编译器也可以用任何其他操作来代替乘法,这些操作在相同的情况下会产生相同的陷阱。)
在没有陷阱的情况下,假设乘以1.0是一个单位变换,则可以消除函数f
的整个主体,因为标准要求float
值的集合是double
值的集合(可能是同一集合)的子集。因此,float->double->float往返行程必须返回到原始值或陷阱。(§3.9.1p8:"类型float
的值集是类型double
的值集的子集"。§4.8p1:"浮点类型的prvalue可以转换为另一个浮点类型的pr value。如果源值可以在目标类型中精确表示,则转换的结果就是该精确表示。")
所以,是的,优化是可能的。但这并不影响?:
表达式的类型,在该类型是可观察的情况下(例如,如果该表达式用于模板推导或用作decltype
的操作数)。
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 与'operator='不匹配(操作数类型'String'且"void")
- 不正确的操作数类型 MSVC
- C2678 二进制 '==':未找到采用 'Card' 类型左操作数的运算符(或者没有可接受的转换)
- 错误:类型"double()"和"double()"的操作数无效到二进制&quo
- C2679 二进制"<<":未找到采用右操作数类型的运算符
- int* 和 int[] 类型对二进制运算符 + 的操作数无效
- 错误:二进制'operator*' 'float'和'float[0]'类型的操作数无效
- 运算符'<'不能应用于类型 'string' 和 'string' 的操作数
- 非法,左操作数具有类型 'DWORD [29]'
- 错误 C2679 二进制"<<":未找到采用类型为 'T' 的右侧操作数的运算符
- 二进制 '==':未找到采用 'Enemy' 类型左侧操作数的运算符(或者没有可接受的转换)
- 错误:'operator>'不匹配(操作数类型为 'Student' 和 'Student'
- 与"运算符>>"不匹配(操作数类型为"QDataStream"和"QJsonObject")
- 类型"int"和"const char [15]"到二进制"运算符<<"的无效操作数^
- 与'operator<<'不匹配(操作数类型'std::ostream {aka std::basic_ostream<char>}'
- c++ 错误:二进制"运算符+"类型"矩阵*"和"矩阵*"的操作数无效
- c++运算符重载-我实际返回的操作数类型是什么
- 无效的类型操作数
- 如何计算重载运算符在具有特定类型操作数的代码库中使用的次数