调用复制构造函数而不是移动构造函数,为什么?
copy constructor called instead of move constructor, why?
考虑这个 class:
template<typename T> struct pooled_resource: T{
template<typename... Args> pooled_resource(std::list<T>& pool, Args&&... args):
T(select_resource(pool, std::forward<Args>(args)...)), pool(pool){
if(!pool.empty()) pool.pop_front();
}
~pooled_resource(){
pool.push_front(static_cast<T&&>(*this));
}
private:
std::list<T>& pool;
template<typename... Args> static T select_resource(std::list<T>& pool, Args&&... args){
if(pool.empty())
return T(std::forward<Args>(args)...);
else
return std::move(pool.front());
}
};
它允许创建具有池化资源但在语义上等同于非池化版本的变量:
std::list<std::vector<int>> pool;
using pooled_vector = pooled_resource<std::vector<int>>;
{
pooled_vector a(pool); //pool is empty, allocate new resources
{ pooled_vector b(pool, 100); } //allocate again, but then release to pool as b goes out of scope
pooled_vector c(pool); //reuse b's resources
assert(c.size() == 100);
}
我的实际问题是,对于上面的简单案例,一切正常,并且调用了池化资源的移动构造函数。但是,我得到另一个 class 没有调用移动构造函数,而是调用复制构造函数。准确地说,class 是 boost::compute::vector,它确实声明了一个移动构造函数,它似乎适用于简单的情况,例如 boost::compute::vector<int> a; boost::compute::vector<int> b(std::move(a));
。
我不知道为什么会发生这种情况,也不知道如何诊断:关于实际使用移动构造函数的规则,我缺少什么?
所以问题是池化资源 class 中的一个愚蠢错误。这是草图:
template<typename T, typename Allocator = DefaultAllocator> struct Resource{
/*...*/
Resource(Resource<T>&& o){ /*...*/ }
}
问题在于移动构造函数的参数类型为 Resource<T, DefaultAllocator>
。由于我使用的是一些自定义分配器,因此实际上没有模板移动构造函数可用于泛型 Allocator
,而只有泛型类型 T
和分配器 DefaultAllocator
。修复只需要省略移动构造函数的所有模板规范:
Resource(Resource&& o){ /*...*/ }
希望这可以节省其他人的下午。
考虑这个 class:
template<typename T> struct pooled_resource: T{
template<typename... Args> pooled_resource(std::list<T>& pool, Args&&... args):
T(select_resource(pool, std::forward<Args>(args)...)), pool(pool){
if(!pool.empty()) pool.pop_front();
}
~pooled_resource(){
pool.push_front(static_cast<T&&>(*this));
}
private:
std::list<T>& pool;
template<typename... Args> static T select_resource(std::list<T>& pool, Args&&... args){
if(pool.empty())
return T(std::forward<Args>(args)...);
else
return std::move(pool.front());
}
};
它允许创建具有池化资源但在语义上等同于非池化版本的变量:
std::list<std::vector<int>> pool;
using pooled_vector = pooled_resource<std::vector<int>>;
{
pooled_vector a(pool); //pool is empty, allocate new resources
{ pooled_vector b(pool, 100); } //allocate again, but then release to pool as b goes out of scope
pooled_vector c(pool); //reuse b's resources
assert(c.size() == 100);
}
我的实际问题是,对于上面的简单案例,一切正常,并且调用了池化资源的移动构造函数。但是,我得到另一个 class 没有调用移动构造函数,而是调用复制构造函数。准确地说,class 是 boost::compute::vector,它确实声明了一个移动构造函数,它似乎适用于简单的情况,例如 boost::compute::vector<int> a; boost::compute::vector<int> b(std::move(a));
。
我不知道为什么会发生这种情况,也不知道如何诊断:关于实际使用移动构造函数的规则,我缺少什么?
所以问题是池化资源 class 中的一个愚蠢错误。这是草图:
template<typename T, typename Allocator = DefaultAllocator> struct Resource{
/*...*/
Resource(Resource<T>&& o){ /*...*/ }
}
问题在于移动构造函数的参数类型为 Resource<T, DefaultAllocator>
。由于我使用的是一些自定义分配器,因此实际上没有模板移动构造函数可用于泛型 Allocator
,而只有泛型类型 T
和分配器 DefaultAllocator
。修复只需要省略移动构造函数的所有模板规范:
Resource(Resource&& o){ /*...*/ }
希望这可以节省其他人的下午。