error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists when using icc 17.0
error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists when using icc 17.0
当我尝试使用特定的编译器版本进行编译时出现编译器错误。
IE。 icc 17.0 -std=c++17 -O3
编译器错误:
source>(19): error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists
Data temp{std::forward<Data>(d)};
^
compilation aborted for <source> (code 2)
ASM generation compiler returned: 2
<source>(19): error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists
Data temp{std::forward<Data>(d)};
^
compilation aborted for <source> (code 2)
Execution build compiler returned: 2
代码:
#include <string>
#include <vector>
#include <iostream>
struct Data {
std::string id{};
std::string rowData{};
int totalRawDataLength{};
std::vector<int> rawDataOffset{};
std::vector<int> rawDataLength{};
Data() = default;
Data(const Data&d) =default;
Data(Data &&d) =default;
};
Data ProcessData(Data &&d) {
Data temp{std::forward<Data>(d)};
// some code
return temp;
}
int main() {
Data d{};
d.id = "id_001";
d.rowData = "some data";
d.rawDataOffset.emplace_back(4);
d.rawDataLength.emplace_back(4);
auto x = ProcessData(std::move(d));
std::cout << "Test:" << x.id << std::endl;
return 0;
}
以下代码适用于所有版本的 gcc
,它适用于具有相同编译器选项的更高版本的 icc。
它甚至适用于 -std=c++11 -O3
for icc 17.0
进一步调试发现正在生成的默认复制构造函数有问题。
我无法理解发生了什么问题,听说是某种编译器错误在以后的版本中得到解决了吗?
这是另一个关于 the fickle aggregate 发生的奇怪例子,这里还有 ICC 编译器(版本 17.0)中一个有争议的错误。
Data
是 C++14 和 C++17 中的聚合 class(但在 C++11 中不是)
在 C++11 中,聚合 class 被定义为,根据 [dcl.init.aggr]/1 (N3337) [emphasis 我的]:
An aggregate is an array or a class (Clause [class]) with no user-provided constructors ([class.ctor]), no brace-or-equal-initializers for non-static data members ([class.mem]), no private or protected non-static data members (Clause [class.access]), no base classes (Clause [class.derived]), and no virtual functions ([class.virtual]).
在C++14和C++17中,除了后者的一些explicit
细节外,规则与C++11中的大部分相同,除了要求
[...] no brace-or-equal-initializers for non-static data members
已删除。
因此,由于您的 class Data
没有 用户提供的 构造函数(参见 [dcl.fct.def.default]/4)而且只有 public 数据成员,它是 C++14 和 C++17 中的聚合,而由于其默认成员初始值设定项,它不是 C++11 中的聚合。
ICC 错误地为 C++14 和 C++17 应用聚合初始化,其中 Data
是一个聚合
现在,下面是direct-braced-init初始化
Data temp{std::forward<Data>(d)}
将在 C++11 中枚举构造函数重载,而在 C++14 和 C++17 中它是直接初始化,特别是通过以下规则(来自 cppreference:
The effects of list initialization of an object of type T are:
- If T is an aggregate class and the initializer list has a single element of the same or derived type (possibly cv-qualified), the
object is initialized from that element (by copy-initialization for
copy-list-initialization, or by direct-initialization for
direct-list-initialization).
如果上述项目符号的条件不适用,聚合的直接大括号初始化 class 将是聚合初始化。这 不应该发生在这里 ,但 ICC 似乎错误地应用了 C++14 和 C++17 中的聚合初始化(其中 Data
是聚合 class),使用 std::forward<Data>(d)
直接初始化 Data
的第一个数据成员(即类型 std::string
的数据成员 id
)而不是直接初始化 Data
本身;所有其他数据成员均由其关联的默认成员初始值设定项初始化。
用用户提供的构造函数替换显式默认的构造函数会使聚合 class 成为非聚合 [=78=]
[...] on further debugging found out that something is wrong with default copy constructor which is being generated.
在此处显示的示例中,您只是 提供了 自己的复制构造函数,与在第一次声明时显式默认它相比。这意味着 class Data
不再是聚合(在 C++11 到 C++17 的任何一个中)。
C++20 理清了大部分早期的聚合混淆
请注意,根据 C++20,根据 P1008R1 的实现,大部分聚合混淆已得到解决(禁止使用用户声明的构造函数进行聚合 ),特别是不再允许聚合具有用户声明的构造函数,class成为聚合的要求比仅仅禁止用户提供的更严格 个构造函数。
当我尝试使用特定的编译器版本进行编译时出现编译器错误。
IE。 icc 17.0 -std=c++17 -O3
编译器错误:
source>(19): error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists
Data temp{std::forward<Data>(d)};
^
compilation aborted for <source> (code 2)
ASM generation compiler returned: 2
<source>(19): error: no suitable user-defined conversion from "Data" to "std::__cxx11::string" exists
Data temp{std::forward<Data>(d)};
^
compilation aborted for <source> (code 2)
Execution build compiler returned: 2
代码:
#include <string>
#include <vector>
#include <iostream>
struct Data {
std::string id{};
std::string rowData{};
int totalRawDataLength{};
std::vector<int> rawDataOffset{};
std::vector<int> rawDataLength{};
Data() = default;
Data(const Data&d) =default;
Data(Data &&d) =default;
};
Data ProcessData(Data &&d) {
Data temp{std::forward<Data>(d)};
// some code
return temp;
}
int main() {
Data d{};
d.id = "id_001";
d.rowData = "some data";
d.rawDataOffset.emplace_back(4);
d.rawDataLength.emplace_back(4);
auto x = ProcessData(std::move(d));
std::cout << "Test:" << x.id << std::endl;
return 0;
}
以下代码适用于所有版本的 gcc
,它适用于具有相同编译器选项的更高版本的 icc。
它甚至适用于 -std=c++11 -O3
for icc 17.0
进一步调试发现正在生成的默认复制构造函数有问题。
我无法理解发生了什么问题,听说是某种编译器错误在以后的版本中得到解决了吗?
这是另一个关于 the fickle aggregate 发生的奇怪例子,这里还有 ICC 编译器(版本 17.0)中一个有争议的错误。
Data
是 C++14 和 C++17 中的聚合 class(但在 C++11 中不是)
在 C++11 中,聚合 class 被定义为,根据 [dcl.init.aggr]/1 (N3337) [emphasis 我的]:
An aggregate is an array or a class (Clause [class]) with no user-provided constructors ([class.ctor]), no brace-or-equal-initializers for non-static data members ([class.mem]), no private or protected non-static data members (Clause [class.access]), no base classes (Clause [class.derived]), and no virtual functions ([class.virtual]).
在C++14和C++17中,除了后者的一些explicit
细节外,规则与C++11中的大部分相同,除了要求
[...] no brace-or-equal-initializers for non-static data members
已删除。
因此,由于您的 class Data
没有 用户提供的 构造函数(参见 [dcl.fct.def.default]/4)而且只有 public 数据成员,它是 C++14 和 C++17 中的聚合,而由于其默认成员初始值设定项,它不是 C++11 中的聚合。
ICC 错误地为 C++14 和 C++17 应用聚合初始化,其中 Data
是一个聚合
现在,下面是direct-braced-init初始化
Data temp{std::forward<Data>(d)}
将在 C++11 中枚举构造函数重载,而在 C++14 和 C++17 中它是直接初始化,特别是通过以下规则(来自 cppreference:
The effects of list initialization of an object of type T are:
- If T is an aggregate class and the initializer list has a single element of the same or derived type (possibly cv-qualified), the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
如果上述项目符号的条件不适用,聚合的直接大括号初始化 class 将是聚合初始化。这 不应该发生在这里 ,但 ICC 似乎错误地应用了 C++14 和 C++17 中的聚合初始化(其中 Data
是聚合 class),使用 std::forward<Data>(d)
直接初始化 Data
的第一个数据成员(即类型 std::string
的数据成员 id
)而不是直接初始化 Data
本身;所有其他数据成员均由其关联的默认成员初始值设定项初始化。
用用户提供的构造函数替换显式默认的构造函数会使聚合 class 成为非聚合 [=78=]
[...] on further debugging found out that something is wrong with default copy constructor which is being generated.
在此处显示的示例中,您只是 提供了 自己的复制构造函数,与在第一次声明时显式默认它相比。这意味着 class Data
不再是聚合(在 C++11 到 C++17 的任何一个中)。
C++20 理清了大部分早期的聚合混淆
请注意,根据 C++20,根据 P1008R1 的实现,大部分聚合混淆已得到解决(禁止使用用户声明的构造函数进行聚合 ),特别是不再允许聚合具有用户声明的构造函数,class成为聚合的要求比仅仅禁止用户提供的更严格 个构造函数。