【发布时间】:2020-12-16 12:14:55
【问题描述】:
在尝试了解与 this question 相关的编译器行为(gcc 和 clang)时,我只是不明白为什么 gcc 和 clang 之间的第三种情况(如下所示)存在差异。问题不是关于这种转换 API 的正确性(尤其是参考案例)。
能否请您帮助我了解在这种情况下预期的行为(从 c++ 标准的角度来看)是什么?
编辑:如 cmets 中所述,这种行为只能在 -std=c++17 的 clang 中观察到。在此之前,引用转换和 gcc 一样使用。
EDIT2:请注意,正确的行为“似乎”是 gcc,因为隐式 this 参数不是 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;
}
感谢您的帮助。
【问题讨论】:
-
向版本标签发送垃圾邮件只会使确定答案变得更加困难。请仅限于您真正感兴趣的标准。
-
@StoryTeller-UnslanderMonica 感谢您的提示!我只是想接触更广泛的受众,但你说得对,因为我只对最新版本感兴趣
-
有趣的是,如果
-std=c++14,clang 的作用与 gcc 相同。我认为 C++17 中的 RVO 使operator T()优于operator T&()+T(T const&)。而在c++14中,operator T&()+T(T const&)优于operator T()+T(T const&),因为T&与T const&的匹配比T更好。参考:over.match.best -
@RedFog 两个编译器都知道保证复制省略。你不觉得反其道而行之吗? Clang 选择按值版本,然后,当它按值返回时,应用一些优化。先重载分辨率。
-
@nop666 在我看来,RVO 在 clang 的隐式转换序列中被考虑,但在 gcc 中却不是。但是我问的一些律师说,
operator T()和operator T&都是 exact match ,所以选择operator T&()更好,因为s是非常量的。所以也等待更多的答案。
标签: c++ c++17 language-lawyer