gcc中不可移动构造函数对象的std::函数
std::function for not MoveConstructible function object in gcc
我正在努力与std::function
相处。从这里的引用可以看出,std::function
的ctor的参数应该是可调用的,并且是可复制构造的。这里有一个小例子:
#include <iostream>
#include <type_traits>
#include <functional>
class A {
public:
A(int a = 0): a_(a) {}
A(const A& rhs): a_(rhs.a_) {}
A(A&& rhs) = delete;
void operator() ()
{
std::cout << a_ << std::endl;
}
private:
int a_;
};
typedef std::function<void()> Function;
int main(int argc, char *argv[])
{
std::cout << std::boolalpha;
std::cout << "Copy constructible: "
<< std::is_copy_constructible<A>::value << std::endl;
std::cout << "Move constructible: "
<< std::is_move_constructible<A>::value << std::endl;
//Function f = A();
return 0;
}
我们有可调用的、可复制的、但不能移动的可构造类。因为我认为这应该足以将其封装在Function
中。但若取消注释注释行,编译器会对删除的move构造函数感到非常不安。这是视频链接。GCC 4.8.0也没有对此进行编译。
那么,这是我对std::function
的误解,还是GCC的错误行为?
GCC和Clang是正确的。
§17.6.3.1.1模板参数要求[实用程序参数要求]
表20--MoveConstructable需求[moveConstructable]
- T u=rv;u等于rv的值施工前
- T(rv);T(rv)等于rv的值施工前
表21--除了MoveConstructible)[可复制构造]
- T u=v;v的值不变,等于u
- T(v);价值v不变并且等价于T(v)
注意:
CopyConstructable要求(除MoveConstructable外)
也就是说,如果某个东西是CopyConstructible,它也必须是MoveConstructible。尽管将移动作为副本来实现是可以的。
更新:
虽然我觉得有趣的是,C++11标准似乎没有根据CopyConstructable来定义is_copy_constructible
,即它们不完全相同,但is_copy_constructible
更宽松,因为它只需要:
§20.9.4.3类型属性[meta.unary.prop]
表49——类型属性谓词
- is_copy_constructible<T>;is_constructible<T、 常量T>;:值为true
您误解了删除规范的目的。移动构造函数不是默认实现的。如果你试图在没有移动ctor的情况下移动一个对象,它只会被复制。如果您将move构造函数指定为已删除,它将尝试调用它,然后查看它是否已删除。这意味着:不能复制临时对象。删除move构造函数语句,它就会工作。
编辑-澄清:
如果没有声明移动构造函数(其中=delete是一个声明),则来自临时对象的构造将调用复制构造函数(来自const引用)。如果您声明一个move构造函数,则来自临时对象的构造将尝试调用此构造函数。因此,如果您声明move-ctor已删除,它将尝试调用delete函数,这将导致错误。如果您不声明它,它将导致对复制ctor的调用。
这就是为什么您的示例不起作用的原因,如果您不声明它,std::函数将只使用copy ctor。
默认情况下,我的意思是:如果未声明,则实现,就像使用复制或默认ctor一样。
- 将对象移动到std::shared_ptr
- 使用std::函数映射对象方法
- 使用"std::unordereded_map"映射到"std::list"对象
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 如何使用std::min和std::less返回对象
- 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?
- C++11 中不同类型的对象的 std::array 的替代方案
- 返回一个带有 std::move 的对象并链接函数
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- std::string 的对象真的可以移动吗?
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 即发即弃 std::线程对象清理自身
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- 传递 std::vector of std::shared_ptr,而不是更新对象
- std::对象映射或对象指针
- 来自std ::对象向量的基础数据
- 在std::对象列表中快速搜索和删除
- 在不同 DLL 之间传递的 std 对象