- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
目前,我正在尝试理解C++标准中的[over.match.oper]/7段落,但是遇到以下情况,其中GCC和Clang会产生不同的结果:
https://wandbox.org/permlink/WpoMviA4MHId7iD9
#include <iostream>
void print_type(int) { std::cout << "int" << std::endl; }
void print_type(int*) { std::cout << "int*" << std::endl; }
struct X { X(int*) {} };
struct Y { operator double() { return 0.0; } };
int operator+(X, int) { return 0; } // #1
// T* operator+(T*, std::ptrdiff_t); // #2: a built-in operator (N4659 16.6/14)
int main() {
int* p = 0;
Y y;
print_type(p + y); // This line produces different results for different compilers:
// - gcc HEAD 8.0.0 : always "int" (#1 is called)
// - clang HEAD 6.0.0 : always "int*" (#2 is called)
// - my understanding : "int*" until C++11, ill-formed since C++14
return 0;
}
If a built-in candidate is selected by overload resolution, the operands of class type are converted to the types of the corresponding parameters of the selected operation function, except that the second standard conversion sequence of a user-defined conversion sequence (16.3.3.1.2) is not applied. Then the operator is treated as the corresponding built-in operator and interpreted according to Clause 8. [Example:
struct X {
operator double();
};
struct Y {
operator int*();
};
int *a = Y() + 100.0; // error: pointer arithmetic requires integral operand
int *b = Y() + X(); // error: pointer arithmetic requires integral operand- end example]
If a built-in candidate is selected by overload resolution, the operands are converted to the types of the corresponding parameters of the selected operation function. Then the operator is treated as the corresponding built-in operator and interpreted according to clause 5.
#1
(
16.3.1.2/(3.2))和内置运算符
#2
(
16.3.1.2/(3.3),
16.6/14)。接下来,为了确定可行函数集,通过为每个自变量/参数对构造隐式转换序列(ICS)来测试两个算子的生存能力。所有ICS均已成功构建为
ICS1(#1) = int* → X
(
16.3.3.1.2,用户定义的转换序列),
ICS2(#2) = Y → double → int
(用户定义的转换序列),
ICS1(#2) = int* → int*
(
16.3.3.1/6,标识转换,标准转换序列之一)和
ICS2(#2) = X → double → std::ptrdiff_t
(用户定义的转换序列) ),因此这两家运营商都是可行的。然后,通过比较ICS来选择最佳可行功能;由于
ICS1(#2)
优于
ICS1(#1)
(
16.3.3.2/(2.1)),并且
ICS2(#2)
不比
ICS2(#1)
(
16.3.3.2/3)差,因此
#2
比
#1
(
16.3.3/1)更好。最后,通过重载分辨率(
16.3.3/2)选择内置运算符
#2
。
(int*) y + (std::ptrdiff_t) (double) n
,这很好。而在C++ 14中,未应用用户定义的转换序列中的第二个标准转换序列,因此考虑使用
(int*) y + (double) n
。这导致违反语义规则(
8.7/1),即表达式格式错误,并且需要执行才能发出诊断消息。
#2
并在8.7/1违规时不带任何诊断消息的情况下调用它。我的猜测是Clang在将调用转移到内置规则(8.7/1)之前完全将ICS应用于参数,这是一个错误。
#1
而不进行诊断。 Visual Studio 2017中的Microsoft C/C++编译器的行为似乎相同。另外,这种行为对我来说似乎很合理(
编辑:请参阅[1])。
#2
不可行,然后只有可行的功能才是
#1
。但是,我找不到任何规则,例如,如果在用户定义的转换序列中没有第二个标准转换序列,内置运算符的格式就会变得不可行。实际上,当CWG 1687引入短语“用户定义的转换序列的第二标准转换序列除外”时,似乎对生存力的定义没有其他修改。
最佳答案
我同意你的解释。我们有int*
和Y
类型的参数,并且有两个候选者:
operator+(X, int); // #1
operator+(int*, std::ptrdiff_t ); // #2
#1
需要两个用户定义的转换序列,
#2
需要一个标准转换序列(完全匹配,尽管无关紧要)和一个用户定义的转换序列。对于第一个参数,标准转换序列
is better than是用户定义的转换序列,而对于第二个参数,这两个序列是无法区分的(
these conditions均不适用)。由于
#2
中的第一个隐式转换序列比
#1
中的第一个隐式转换序列更好,并且第二个转换序列是等效的
#2
wins。
double
到
ptrdiff_t
的最后一次转换,因此结果应该格式错误。
is the behavior intended by CWG 1687?
int *b = Y() + X(); // error: pointer arithmetic requires integral operand
Y()
可转换为
int*
而不是直接转换为
int*
。我继续提交了
gcc 81789和
llvm 34138。请注意,clang根本没有实现CWG 1687,该问题的示例和标准编译中均未实现。
关于c++ - 在运算符表达式上下文中纠正重载解析的内置运算符候选的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45602368/
假设我有一个类,我在其中重载了运算符 == : Class A { ... public: bool operator== (const A &rhs) const; ... };
我知道你不应该使用 std::find(some_map.begin(), some_map.end()) 或 std::lower_bound,因为它会采用线性时间而不是 some_map.lowe
我正在尝试在 Haskell 中定义 Vector3 数据类型,并允许在其上使用 (+) 运算符。我尝试了以下方法: data Vector3 = Vector3 Double Double Doub
我已经为我的类图将运算符重载为“-”。它的用途并不完全直观(糟糕的编码 - 我知道)但是如果我做 graph3 = graph2-graph1 那么图 3 是应该只接收图 2 和图 1 中的那些顶点。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Operator overloading 我想重载 以按字母顺序排列字符串,但我不确定该怎么做。 如何再次
下面的代码给我一个编译错误。谁能告诉我为什么? class mytype { public: int value; mytype(int a) { value = a;
这有什么问题吗? class Vec2 attr_accessor :x, :y # ... def += (v) @x += v.x @y += v.y retu
是否可以重载 [] 运算符两次?允许这样的事情:function[3][3](就像在二维数组中一样)。 如果可能的话,我想看看一些示例代码。 最佳答案 您可以重载 operator[] 以返回一个对象
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
我有一个网页,在某个时候显示一个导航栏,它只不过是一个 a 元素的列表 (ul)。所述 a 元素的大多数样式规则都是通用的。唯一应该改变的部分是要显示的图像,可以从列表中每个 li 元素的 id 标签
我对使用/重载“范围步长”运算符(.. ..)很感兴趣,但我终其一生都无法了解如何使用它。 在文档中它说 // Usage: start .. step .. finish 但是在 F# shell
Java 11(可能无关紧要): public static String toString(Object obj) { return ReflectionToStringBuilder.to
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我无法理解以下代码(针对行号进行注释) class Base { void m1(Object o) { } void m2(String o) { } } publi
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
class myclass{ //definitions here }; myclass e; int myarray[10]; /* Do something... */ e = myarray;
为什么不能将下标运算符(operator [])作为 friend 函数重载? 最佳答案 正如Bjarne Stroustrup在D&E book中所说: However, even in the o
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
因此,我有一个问题是我最近尝试重载 namespace Eng { /** * A structure to represent pixels */ typedef
如何重载onResume()以正确的方式工作?我想从 activity 返回到 MainActivity ,我希望在其中具有与应用程序启动后相同的状态。我想使用 recreate() 但它循环了或者类
我是一名优秀的程序员,十分优秀!