为何检查二维数组元素类型时std::is_same_v返回0?
问题原因与解决方案
你的问题核心在于**decltype推导保留了引用类型,而std::is_same_v会严格区分引用与非引用类型**,但typeid和sizeof的行为让你产生了类型一致的错觉。
具体分析
decltype的推导结果:
当你调用std::declval<arr>()[0][0]时,std::declval<arr>()返回的是arr&&(二维数组的右值引用),[0]操作会返回一维数组的左值引用std::int32_t(&)[N],再调用[0]则返回元素的左值引用std::int32_t&。decltype对左值表达式会推导为引用类型,因此decltype(std::declval<arr>()[0][0])的实际类型是std::int32_t&,而非你预期的std::int32_t。std::is_same_v的严格比较:std::is_same_v<T, U>仅当T和U是完全相同的类型时才返回true。引用类型std::int32_t&和非引用类型std::int32_t被视为不同类型,因此结果输出0。typeid与sizeof的误导性:typeid会忽略引用和cv限定符,typeid(std::int32_t&)与typeid(std::int32_t)返回的是同一个类型信息对象,所以你看到的类型名称一致。sizeof引用时,会返回被引用类型的大小,因此sizeof(std::int32_t&)等于sizeof(std::int32_t)(4字节),进一步让你误以为类型完全匹配。
修复代码示例
使用std::remove_reference_t去掉引用属性后再进行比较:
#include <type_traits> #include <cstdint> #include <iostream> #include <typeinfo> int main() { using arr = std::int32_t[2][3]; // 示例二维数组类型 // 原代码:比较引用类型与非引用类型,返回false std::cout << std::is_same_v<decltype(std::declval<arr>()[0][0]), std::int32_t> << '\n'; // 输出0 // 修复:去掉引用后比较,返回true using elem_type = std::remove_reference_t<decltype(std::declval<arr>()[0][0])>; std::cout << std::is_same_v<elem_type, std::int32_t> << '\n'; // 输出1 // 验证类型信息 std::cout << "typeid of declval result: " << typeid(decltype(std::declval<arr>()[0][0])).name() << '\n'; std::cout << "typeid of int32_t: " << typeid(std::int32_t).name() << '\n'; std::cout << "sizeof of declval result: " << sizeof(decltype(std::declval<arr>()[0][0])) << '\n'; return 0; }
总结
- 不要依赖
typeid或sizeof来判断类型是否完全一致,它们无法区分引用、cv限定符等细节。 - 用
std::is_same_v时,务必确保比较的类型在引用、cv限定等属性上完全匹配,必要时用std::remove_reference_t、std::remove_cv_t等工具调整类型。
内容的提问来源于stack exchange,提问作者Jaan
相关产品推荐
相关产品推荐

