我注意到#include <iostream>
#include <sstream>
void f(const char * str)
{
std::cout << str << std::endl;
}
std::string str(void (*populate)(std::ostream &))
{
std::ostringstream stream;
populate(stream);
return stream.str();
}
int main(int argc, char * * args)
{
f(str([](std::ostream & ss){ ss << "Value: " << 5; }).c_str());
return 0;
}
// g++ -std=c++11 main.cpp -o main
// ./main
// Value: 5
可以应用于不与&#34;非平凡&#34; (完全不知道,但例如原始类型很好)成员。例如,以下代码编译(C ++ 14,Clang):
move
请注意,复制构造函数已删除。由于#include <vector>
#include <string>
class Foo {
public:
union {
int i;
bool b;
};
Foo() {};
~Foo() {};
// Move constructor to default.
Foo(Foo &&) = default;
// Copy constructor deleted.
Foo(const Foo &) = delete;
};
int main() {
std::vector<Foo> v;
v.push_back(Foo());
}
std::vector
可以接受右值引用,因此在这种情况下将使用它,并且不会发生push_back
。然而,一旦&#34;非平凡&#34;类型被添加到联合中,强制复制构造函数 - 因此它不会编译:
copy
编译器错误消息的相关部分:
#include <vector>
#include <string>
class Foo {
public:
union {
int i;
bool b;
std::string s; // <-- Added element causing compile error.
};
Foo() {};
~Foo() {};
// Move constructor to default.
Foo(Foo &&) = default;
// Copy constructor deleted.
Foo(const Foo &) = delete;
};
int main() {
std::vector<Foo> v;
v.push_back(Foo());
}
我知道有关可以移动的内容和不可移动的内容的一些规则,但这似乎无关紧要。为什么会发生这种情况,如何解决这个问题,因此它不会调用复制构造函数?
目标编译器是Clang C ++ 14。
答案 0 :(得分:2)
它试图调用您的复制构造函数,因为您的移动构造函数已删除。哦,当然,我知道你写过= default
。但是由于union包含一个带有非平凡移动/复制构造函数的类型,如果不是用户提供的,union的复制/移动构造函数将被隐式删除。
并且= default
没有提供&#34;用户提供&#34;。
换句话说,如果编译器的任何成员需要复制/移动union
以外的代码,编译器就不能给memcpy
一个复制/移动构造函数(又名:不是平凡的可复制的)。因此,包含union的类型也不能具有编译器生成的复制/移动代码。在这些情况下,您必须决定如何复制/移动对象。
这样的复制/移动构造函数需要知道它是哪种类型。