C++右值引用类型匹配断言错误排查与修正咨询
C++引用折叠测试:static_assert错误分析与修正
问题背景
在测试左值引用、右值引用的组合类型时,出现两个static_assert断言失败,需要理解原因并修正代码。
原始代码
#include <assert.h> typedef int& IntLRef; typedef IntLRef& IntLLRef; typedef IntLRef&& IntLRRef; typedef int&& IntRRef; typedef IntRRef& IntRLRef; typedef IntRRef&& IntRRRef; template<typename T, typename U> struct IsSameType { static const bool value = false; }; template<typename T> struct IsSameType <T, T> { static const bool value = true; }; static_assert(IsSameType<IntLRef, IntLLRef>::value, "LRef DIF LLRef"); static_assert(IsSameType<IntLRef, IntLRRef>::value, "LRef DIF LRRef"); static_assert(IsSameType<IntLLRef, IntLRRef>::value, "LLRef DIF LRRef"); static_assert(IsSameType<IntRRef, IntRLRef>::value, "RRef DIF RLRef"); static_assert(IsSameType<IntRRef, IntRRRef>::value, "RRef DIF RRRef"); static_assert(IsSameType<IntRLRef, IntRRRef>::value, "RLRef DIF RRRef"); int main();
错误信息
rvalue_ex3.cpp:34:48: error: static assertion failed: RRef DIF RLRef 34 | static_assert(IsSameType<IntRRef, IntRLRef>::value, "RRef DIF RLRef"); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ rvalue_ex3.cpp:36:49: error: static assertion failed: RLRef DIF RRRef 36 | static_assert(IsSameType<IntRLRef, IntRRRef>::value, "RLRef DIF RRRef"); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
核心原因:C++引用折叠规则
C++不允许存在"引用的引用"这种类型,编译器会自动将其折叠为单一引用,规则如下:
T& &→T&(左值引用的左值引用折叠为左值引用)T& &&→T&(左值引用的右值引用折叠为左值引用)T&& &→T&(右值引用的左值引用折叠为左值引用)T&& &&→T&&(右值引用的右值引用折叠为右值引用)
对应到你的代码:
IntRLRef是IntRRef&,而IntRRef是int&&,所以IntRLRef等价于int&& &,折叠后是int&,和IntRRef(int&&)不是同类型,导致第一个错误断言失败。IntRRRef是IntRRef&&,等价于int&& &&,折叠后是int&&(即IntRRef);但IntRLRef是int&,和IntRRRef(int&&)类型不同,导致第二个错误断言失败。
修正方案
根据引用折叠规则,调整断言或typedef,使其符合实际的类型等价性:
方案1:修正断言以匹配实际类型
如果你的目标是验证引用折叠的结果,修改断言如下:
#include <assert.h> typedef int& IntLRef; typedef IntLRef& IntLLRef; typedef IntLRef&& IntLRRef; typedef int&& IntRRef; typedef IntRRef& IntRLRef; typedef IntRRef&& IntRRRef; template<typename T, typename U> struct IsSameType { static const bool value = false; }; template<typename T> struct IsSameType <T, T> { static const bool value = true; }; // 左值引用相关断言(原本就正确,因为所有左值引用的组合都折叠为左值引用) static_assert(IsSameType<IntLRef, IntLLRef>::value, "LRef DIF LLRef"); static_assert(IsSameType<IntLRef, IntLRRef>::value, "LRef DIF LRRef"); static_assert(IsSameType<IntLLRef, IntLRRef>::value, "LLRef DIF LRRef"); // 修正后的右值引用相关断言 static_assert(IsSameType<IntRLRef, IntLRef>::value, "RLRef DIF LRef"); // IntRLRef实际是int&,和IntLRef同类型 static_assert(IsSameType<IntRRef, IntRRRef>::value, "RRef DIF RRRef"); // IntRRRef实际是int&&,和IntRRef同类型 static_assert(IsSameType<IntRLRef, IntRRRef>::value == false, "RLRef EQ RRRef"); // int&和int&&类型不同 int main();
方案2:修正typedef以匹配原断言意图
如果你希望原断言全部成立,可以直接将typedef定义为折叠后的实际类型:
#include <assert.h> typedef int& IntLRef; typedef IntLRef& IntLLRef; typedef IntLRef&& IntLRRef; typedef int&& IntRRef; typedef int& IntRLRef; // 直接定义为折叠后的int& typedef IntRRef&& IntRRRef; template<typename T, typename U> struct IsSameType { static const bool value = false; }; template<typename T> struct IsSameType <T, T> { static const bool value = true; }; static_assert(IsSameType<IntLRef, IntLLRef>::value, "LRef DIF LLRef"); static_assert(IsSameType<IntLRef, IntLRRef>::value, "LRef DIF LRRef"); static_assert(IsSameType<IntLLRef, IntLRRef>::value, "LLRef DIF LRRef"); // 现在原断言可以成立 static_assert(IsSameType<IntLRef, IntRLRef>::value, "LRef DIF RLRef"); // IntRLRef是int&,和IntLRef同类型 static_assert(IsSameType<IntRRef, IntRRRef>::value, "RRef DIF RRRef"); static_assert(IsSameType<IntLRef, IntRRRef>::value == false, "LRef EQ RRRef"); int main();
内容的提问来源于stack exchange,提问作者AKM
相关产品推荐
相关产品推荐

