使用Clang编译含deducing this的std::forward_like代码时出错
Deducing This特性在Clang编译报错的原因及解决方法
问题背景
尝试用C++23的deducing this特性简化代码库,编写的测试代码在MSVC和GCC中运行正常,但在Clang下编译报错,错误提示std::forward_like推导返回类型的函数未定义、找不到匹配的Get成员函数。
测试代码如下:
#include <iostream> #include <type_traits> #include <utility> class S { public: auto Get(this auto&& self) -> auto&& { return std::forward_like<decltype(self)>(self.val); } private: int val{0}; }; int main() { S const s; std::cout << std::is_rvalue_reference_v<decltype(s.Get())> << '\n'; std::cout << std::is_const_v<std::remove_reference_t<decltype(s.Get())>> << '\n'; std::cout << std::is_rvalue_reference_v<decltype(std::move(s).Get())> << '\n'; std::cout << std::is_const_v<std::remove_reference_t<decltype(std::move(s).Get())>> << '\n'; }
Clang报错信息:
error: function 'forward_like<const S &, const int &>' with deduced return type cannot be used before it is defined note: in instantiation of function template specialization 'S::Get<const S &>' requested here
问题原因
这是Clang对C++23特性的实现细节与GCC、MSVC存在差异导致的:
- Clang中
std::forward_like的实现采用了推导返回类型的函数模板,在类内Get函数的语境下,调用std::forward_like时,该模板的实例化点早于其自身定义完成,触发了"未定义前使用"的错误。 - Deducing this特性在Clang中的处理逻辑,使得
Get函数模板实例化时,对std::forward_like的调用提前触发了未完成的模板实例化,而GCC和MSVC则允许这种提前调用的场景。
解决方法
方法1:改用decltype(auto)作为返回类型
将Get函数的返回类型改为decltype(auto),让编译器直接推导返回值类型,避免依赖std::forward_like的推导返回类型:
#include <iostream> #include <type_traits> #include <utility> class S { public: decltype(auto) Get(this auto&& self) { return std::forward_like<decltype(self)>(self.val); } private: int val{0}; }; int main() { S const s; std::cout << std::is_rvalue_reference_v<decltype(s.Get())> << '\n'; std::cout << std::is_const_v<std::remove_reference_t<decltype(s.Get())>> << '\n'; std::cout << std::is_rvalue_reference_v<decltype(std::move(s).Get())> << '\n'; std::cout << std::is_const_v<std::remove_reference_t<decltype(std::move(s).Get())>> << '\n'; }
方法2:显式指定std::forward_like的返回类型
通过static_cast显式转换到目标类型,绕开推导返回类型的限制:
auto Get(this auto&& self) -> auto&& { using ReturnType = decltype(std::forward_like<decltype(self)>(self.val)); return static_cast<ReturnType>(self.val); }
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

