根据http://en.cppreference.com/w/cpp/utility/functional/function/function,初始化器的类型,即形式(5)中的F
,应满足CopyConstructible的要求。我不太懂。为什么F
只是MoveConstructible不合适?
答案 0 :(得分:4)
std :: function在内部使用类型擦除,因此即使您使用的特定std :: function对象永远不会被复制,F也必须是CopyConstructible。
简化类型擦除的工作原理:
class Function
{
struct Concept {
virtual ~Concept() = default;
virtual Concept* clone() const = 0;
//...
}
template<typename F>
struct Model final : Concept {
explicit Model(F f) : data(std::move(f)) {}
Model* clone() const override { return new Model(*this); }
//...
F data;
};
std::unique_ptr<Concept> object;
public:
template<typename F>
explicit Function(F f) : object(new Model<F>(std::move(f))) {}
Function(Function const& that) : object(that.object->clone()) {}
//...
};
您必须能够生成Model<F>::clone()
,这会强制F为CopyConstructible。
答案 1 :(得分:2)
std::function
是CopyConstructible(请参阅文档中的构造函数(3))。如果可以复制所有组件,则只能复制对象。所以包含的F
也必须是CopyConstructible。很简单。
答案 2 :(得分:2)
来自@Nevin的例子在显示实现选项方面很有启发性。不过,这里有一些更基本的工作。它不是所使用的特定实现技术的工件。
特别是virtual
并不是真正的关键。考虑这种不使用virtual
的替代实现(除了在析构函数中)。
class Function
{
struct Concept {
typedef Concept * (*cloneFunType)(const Concept *);
cloneFunType m_cloneFun = nullptr;
virtual ~Concept() = default;
};
template<typename F> struct Model final : Concept {
static Concept* clone(const Concept *c) {
return new Model(static_cast<const Model*>(c)->data); }
explicit Model(F &&f) : data(move(f)) { this->m_cloneFun = &Model::clone;}
explicit Model(const F &f) : data(f) { this->m_cloneFun = &Model::clone; }
F data;
};
Concept* object;
public:
~Function() { delete object; }
template<typename F> explicit Function(F&& f)
: object(new Model<typename remove_reference<F>::type>(forward<F>(f))) {}
Function(Function const& that)
: object((*(that.object->m_cloneFun))(that.object)) {}
Function(Function && that) : object(that.object) { that.object = nullptr; }
//...
};
请参阅http://ideone.com/FKFktK了解完整版和示例输出
考虑表达式的值(也在http://ideone.com/FKFktK中):
is_copy_constructible<function<void()>>::value
答案不能取决于特定实例的属性或它们的构造方式,在这种情况下甚至没有要查看的实例。可复制性是类型的属性,而不是实例的属性。所以答案必须统一true
或false
在所有情况下。
标准选择is_copy_constructible<function<void()>>::value
为true
。因此,无论std :: function模板的实现内部如何,标准都被迫要求is_copy_constructible<F>::value
也是true
。
如果我们选择is_copy_constructible<function<void()>>::value
为false
,则无论某些特定F
本身是否可复制,都不会复制任何实例。