在试图获得与这个问题相关的编译器行为(gcc和clang)的一些见解时,我只是不明白为什么gcc和clang之间的第三种情况(如下所示)有所不同。问题不是关于这样一个转换API的正确性(尤其是参考案例)。
你能帮我理解一下这个场景中的预期行为吗(从c标准的角度来看)?
编辑:如评论中所述,这种行为仅在clang中从-std=c 17中观察到。在此之前,引用转换与gcc中一样使用。
EDIT2:注意,正确的行为“似乎”是gcc,因为隐式< code>this参数不是< code>const,因此非const重载是首选的...
下面是示例代码:
struct SInternal {
SInternal() = default;
SInternal(const SInternal&) {
std::cout << "copy ctor" << std::endl;
}
int uuid{0};
};
struct S {
SInternal s;
S() = default;
operator SInternal() const {
std::cout << "copy conversion" << std::endl;
return s;
}
operator SInternal& () {
std::cout << "ref conversion" << std::endl;
return s;
}
};
int main() {
S s;
const S s2;
// 1-
//SInternal si = s; // no ambiguity, ref conversion
//SInternal si = s2; // no ambiguity, copy conversion
// 2-
// SInternal& si = s; // no ambiguity, ref conversion
// SInternal& si = s2; // no viable conversion operator SInternal& not const
// Case 3- WHAT IS THE CORRECT EXPECTED BEHAVIOR HERE?
SInternal si(s); // no ambiguity but clang uses copy conversion
// while gcc uses ref conversion
//SInternal si(s2); // no ambiguity, copy conversion
// 4-
//SInternal si = std::move(s); // no ambiguity ref conversion
std::cout << "test " << si.uuid << std::endl;
}
在这里演示。
感谢您的帮助。
以下是我从目前的研究中试图回答我自己的问题,并在评论中提供了善意的帮助。
欢迎评论中的任何评论来改进答案。
答案与这个答案和那个答案密切相关,因此问题本身可能是重复的。
S内部 si;) 的一种
情况。本案属于以下情况:否则,如果初始化是直接初始化,或者是复制初始化,其中源类型的cv非限定版本与目标类的类或其派生类相同,则考虑构造函数。枚举适用的构造函数([over.match.ctor]),并通过重载解析选择最佳构造函数。调用所选的构造函数来初始化对象,并将初始值设定项表达式或表达式列表作为其参数。如果没有应用构造函数,或者重载解析不明确,则初始化格式不正确。
结果:S内部()
和S内部(const S内部
引用必须绑定到SInternal(< code > SInternal
是正在初始化的引用的类型,< code>S是初始值设定项表达式的类型)。这个案子属于over.match.ref:
…考虑了S及其基类的转换函数。那些不隐藏在S中的非显式转换函数,并产生类型“lvalue reference to cv2 T2”(当初始化lvalue引用或函数的rvalue引用时)或“cv2 T1”或“rvalue reforence to cv 2 T2)(当初始化函数的rvalize引用或lvalue reference时),其中“cv1 T”与“cv2T2”的引用兼容([dcl.init.ref]),是候选函数。。。
结果:候选函数为operator SInternal()const
和operator SInternal
结果:
运算符S内部
该行为似乎与其他帖子中解释的CWG 2327有关。
如果这是此类行为的编译器实现,则考虑直接初始化转换函数,并选择
运算符 SInternal () const
。
最后一点是转换操作符的实现。如果< code>SInternal
copy ctor很简单,则不会调用copy构造函数。如果定义了一个空的复制构造函数,那么就调用它(DEMO)。
这是因为SInternal变为“普通可复制”,因此编译器利用它来使用寄存器进行复制。如果您用更多的数据成员填充
SInternal
(例如char arr[32];
>),它最终将使用
给定以下代码(在wandbox上): 和下列编译器选项: cppreference似乎建议语法应该触发显式转换。
自定义运算符 struct Vector2D { var x = 0.0 var y = 0.0 } infix operator +++ extension Vector2D { static func +++ (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left
VC: (34):错误C2593:'运算符='是含糊不清的 (26):注意:可能是测试 (25):注:或“测试” (69):注意:当试图匹配参数列表时'(测试,包装器)' ======生成:0成功,1失败,0最新,0跳过========== 叮当声: : 34:7:错误:重载运算符=的使用不明确(操作数类型为Test和typename std::remove_reference 测试=标准::移动
本文向大家介绍浅谈C++类型转化(运算符重载函数)和基本运算符重载(自增自减),包括了浅谈C++类型转化(运算符重载函数)和基本运算符重载(自增自减)的使用技巧和注意事项,需要的朋友参考一下 类型转化(运算符重载函数) 用转换构造函数可以将一个指定类型的数据转换为类的对象。但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成double类型数据)。在C++提供
我有带转换操作符的简单代码,似乎所有的编译器都给出不同的结果,我很好奇哪个编译器是正确的?我也尝试了不同的组合,但以下是最有趣的。代码是使用C 11标志编译的,但是在C 03中也可能观察到相同的行为。 叮当声-3.6: g -4.9: msvc 2014年CTP: 删除后: msvc编译: 此外,在移除const in后 叮当声-3.6: g -4.9: msvc 2014年CTP:
我在C#中定义了一个类(称为类A),并为它重载了一些算术运算符。让我们关注加法运算符(尽管我希望其他运算符的行为类似)。我已经设置了类A,这样我就可以向它添加标量(即单个Double值),我可以将它添加到标量中,或者我可以将A的两个实例一起添加。 所以在C#中,我用三个不同的签名重载了“”运算符。显式签名是: 一个双人间 < li >双A 答:答:答 当我在PowerShell中使用该类时,它只识