关于无法从“initializer-list”转换为“QJsonObject”解决办法

本文探讨了在使用VS2013编译时遇到的QJsonObject构造问题,主要原因是编译器对C++11的initializer-list语法支持不足。文中提供了几种解决方案,包括更新VS版本或配置文件中启用C++11支持。

一、简述

前些天在工作中使用QJsonObject的构造进行初始化出现了一下的问题。我们先看一下下面QJsonObject的一种构造方法。

这里写图片描述

在我使用的VS2013版本编译时会出现无法从“initializer-list”转换为“QJsonObject”的问题。

问题出在Q_COMPILER_INITIALIZER_LISTS宏定义。(见下图)

class Q_CORE_EXPORT QJsonObject
{
public:
    QJsonObject();

#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
    QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
    {
        initialize();
        for (std::initializer_list<QPair<QString, QJsonValue> >::const_iterator i = args.begin(); i != args.end(); ++i)
            insert(i->first, i->second);
    }
#endif

这里写图片描述

我们看到源码中 Q_COMPILER_INITIALIZER_LISTS 宏其实未定义。
而 该宏定义在qcompilerdetection.h中,具体可以看到

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

其实从上面可以看到有一处是需要支持c++11的,但是旧版本的VS2013对C++11的initialize-list语法不支持。

如果用VS2013 需要更新到 update3以上。支持 initialize-list语法.或者是下载新版本的VS2013安装包,我是直接下载了update5,然后修复了此问题。

在Creator中可以添加
DEFINES += Q_COMPILER_INITIALIZER_LISTS

CONFIG += c++11

windows {
DEFINES *= Q_COMPILER_INITIALIZER_LISTS
}

见以下链接的评论处。
https://www.devbean.net/2016/08/qt-creator-source-study-04/

### 关于C++ Error C2440 的解决方案 Error C2440 是指在初始化过程中,无法将 `initializer list` 转换为目标类型。这种错误通常发生在尝试使用大括号 `{}` 列表初始化某些复杂数据结构时,比如 STL 容器或自定义类。 #### 错误原因分析 该错误的核心在于目标类型的构造函数不支持从 `initializer list` 进行隐式转换。例如,在标准库中的 `std::list<char*>` 类型中,如果试图直接用字符串字面量进行初始化,则会触发此错误[^1]。这是因为 `std::list` 预期的是指向字符数组的指针列表,而提供的初始值却是常量字符串字面量。 --- #### 解决方案 1:修改模板参数以匹配实际需求 对于 `std::list` 或其他类似的容器,可以通过调整其存储的数据类型来解决问题。具体来说,可以将模板参数改为接受常量字符串指针 (`const char*`): ```cpp // 原始代码引发错误 std::list<char*> slist = { "hello", "world", "!" }; // 修改后的代码 std::list<const char*> slist = { "hello", "world", "!" }; ``` 这里的关键变化是从 `char*` 改为 `const char*`,因为字符串字面量本质上是不可变的对象[^1]。 --- #### 解决方案 2:显式创建临时对象并传递给容器 另一种方法是手动构建所需的对象实例,并将其作为参数传入到容器中。这种方法适用于更复杂的场景,尤其是当需要动态分配内存或其他特殊处理时: ```cpp #include <list> #include <string> int main() { std::list<std::string> slist; slist.push_back(std::string("hello")); slist.push_back(std::string("world")); slist.push_back(std::string("!")); return 0; } ``` 这种方式避免了直接操作裸指针带来的潜在风险,同时也解决了兼容性问题[^2]。 --- #### 解决方案 3:移除不必要的默认成员初始化 如果是在结构体或者类内部发生此类错误,可能是因为存在冲突的默认成员初始化逻辑。例如下面的例子展示了如何通过删除这些预设值修复编译失败的情况: ```cpp struct Test { LPCWSTR testName /*= L""*/; // 移除了默认值设定 int testValue /*= 0*/; }; Test tests[] = { {L"Test1", 100}, {L"Test2", 200} }; ``` 此处取消了字段上的自动赋初值语句之后,允许后续利用花括弧形式完成批量设置动作而不违反任何规则[^3]。 --- #### 示例代码展示 以下是综合以上几种策略的一个完整例子: ```cpp #include <iostream> #include <list> using namespace std; int main(){ // 使用 const char * 来代替 char * list<const char *> strList = {"one","two","three"}; for(auto &str : strList){ cout << str << endl; } struct Example{ string name;// 不再提供 inline initialization double value; }; vector<Example> examples={ {"First Item",1.1},{"Second Item",2.2} }; for(const auto& item:examples){ cout<<item.name<<" "<<item.value<<"\n"; } return 0; } ``` --- ### 总结 针对 error C2440 ,主要可以从以下几个方面入手解决: - **确认数据类型一致性** :确保所使用的类型能够正确表示待存贮的内容; - **采用合适的数据结构** :依据具体情况选用最恰当的标准库组件; - **简化设计模式** :减少不必要的额外功能装饰以便更容易维护程序行为; ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值