我正在尝试 C++23 中新的“推导此”功能,发现 gcc 和 clang 不同意的情况,我希望得到一个关于哪个编译器是正确的裁决。我已将我正在处理的原始代码最小化到以下示例中。考虑以下情况:
#include <utility>
#include <type_traits>
struct foo {
int asdf;
template <class T, class O>
using conversion_type = std::conditional_t<
std::is_lvalue_reference_v<O>,
T&,
T
>;
template <class Self>
operator conversion_type<int, Self>(this Self&& self) {
return std::forward<Self>(self).asdf;
}
};
int main() {
foo f;
int& fdsa = f;
int&& asdf = std::move(f);
}
无需过多担心我到底为什么这样做,我试图声明一个隐式转换运算符,该运算符根据要转换的对象的推导值类别来更改其转换为的类型的值类别。
在这种特殊情况下,如果要转换的对象是左值,我希望转换运算符解析为转换为对子对象的左值引用,如果不是,我希望它解析为转换为临时(不是右值引用,我希望它将子对象移动到新的临时对象中)。
gcc 完全愿意编译这段代码,并且它似乎按照我的预期工作。 clang 将编译 main 中的第三行,但不会编译第二行,声称
non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'foo'
,这在我看来甚至没有考虑转换运算符。
鉴于 clang 对此问题的处理似乎不一致,我认为这可能是一个 clang bug,但我想看看一般的看法是什么。
这是演示该问题的编译器资源管理器的链接:https://godbolt.org/z/dG6jTj9rr
如果将编译器切换到任何版本的 gcc 14,它的构建都不会出现问题。有什么想法吗?
这是一个有趣的案例,凸显了编译器处理模板推导和隐式转换运算符的方式的一些复杂性,特别是使用新的 C++23 功能时。
GCC 和 Clang 之间的差异可能源于每个编译器如何实现和解释新的 C++23 功能的差异,尤其是与模板推导相结合的 this 推导参数。您应该将此行为作为潜在错误报告给 Clang 开发人员。包括您在此处提供的简化代码示例和说明,以及编译器资源管理器的链接,对于允许他们重现和诊断问题非常有帮助。
同时,如果您的目标是多个编译器,则可能需要考虑解决方法或避免依赖此特定行为,直到它在 Clang 中得到解决。