Qt6中如何修复demangle函数使QStringList不被解析为QList<QString>
Qt6下demangle无法返回QStringList的问题解决方案
根本原因
Qt6 中QStringList不再是独立继承于QList<QString>的子类,而是被定义为QList<QString>的类型别名:
// Qt6 源码中的定义 using QStringList = QList<QString>;
C++ 标准规定typeid运算符会忽略类型别名,直接返回底层原始类型的类型信息,因此typeid(QStringList)和typeid(QList<QString>)拿到的 mangled name 本身完全一致,abi::__cxa_demangle自然只会解析出QList<QString>,这不是 demangle 函数的逻辑问题,是 Qt 版本迭代导致的类型定义变更。
调整方案
方案1:demangle 函数增加别名兼容映射
如果你的业务只需要和 Qt5 时期的返回值保持一致,不需要区分QStringList和QList<QString>,可以直接在 demangle 函数中增加特例替换:
static QString demangle( const QString &name ) { int status; std::unique_ptr< char, void(*)( void* ) > res ( abi::__cxa_demangle( name.toLatin1().constData(), nullptr, nullptr, &status ), std::free ); QString result = ( status == 0 ) ? QLatin1String( res.get() ) : name; // Qt6 别名兼容 if (result == "QList<QString>") { return "QStringList"; } // 有其他需要兼容的Qt别名也可以在此处添加规则 return result; }
注意:该方案会把所有
QList<QString>的解析结果都替换为QStringList,如果你的逻辑需要区分两种类型不要使用该方案。
方案2:保留两种类型的区分能力
如果你的自研库需要同时支持识别QStringList和QList<QString>,由于typeid本身已经无法区分别名和原始类型,需要放弃依赖typeid的实现,改用模板特化的方式自定义类型名映射:
// 通用类型名获取逻辑 template<typename T> QString get_typed_name() { int status; std::unique_ptr< char, void(*)( void* ) > res ( abi::__cxa_demangle( typeid(T).name(), nullptr, nullptr, &status ), std::free ); return ( status == 0 ) ? QLatin1String( res.get() ) : typeid(T).name(); } // 特化QStringList的返回值 template<> QString get_typed_name<QStringList>() { return "QStringList"; }
使用时直接调用模板函数即可得到和Qt5一致的结果:
ct_Halt( get_typed_name<QStringList>(), get_typed_name<QList<QString>>() ); // 输出结果:QStringList、QList<QString>
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

