我有一个C++框架,我提供给我的用户,他们应该使用我用自己的实现编写的模板包装作为模板类型。 包装器充当RAII类,它包含一个指向用户类实现的指针。 为了使用户的代码干净整洁(在我看来),我提供了一个转换操作符,它将包装器转换为它所包含的指针。这种方式(以及其他一些重载)用户可以使用我的包装,就好像它是一个指针(很像shared_ptr)。C++ std ::移动指针
我遇到了一个角落的情况,用户调用一个函数,该函数使用指向他的实现类的指针,在我的包装上使用std :: move。这里是什么样子的例子:
#include <iostream>
using namespace std;
struct my_interface {
virtual int bar() = 0;
};
template <typename T>
struct my_base : public my_interface {
int bar() { return 4; }
};
struct my_impl : public my_base<int> {};
template <typename T>
struct my_wrapper {
my_wrapper(T* t) {
m_ptr = t;
}
operator T*() {
return m_ptr;
}
private:
T* m_ptr;
};
void foo(my_interface* a) {
std::cout << a->bar() << std::endl;
}
int main()
{
my_impl* impl = new my_impl();
my_wrapper<my_impl> wrapper(impl);
foo(std::move(wrapper));
//foo(wrapper);
return 0;
}
[这是ofcourse只是案件的一个例子,有在包装更多的方法,但我敢肯定,在这里不发挥作用在这种情况下]
用户,如我所料,如果在包装上调用std :: move,那么在调用foo
之后,包装将是空的(或者至少像被移动一样进行修改) ,但实际上在foo
之前调用的唯一方法是演员。
有没有一种方法,使两个调用使用和不std::move
打电话时foo
即区分之间的调用foo
?
编辑 得益于鸣叫鸭的评论,我发现一种方式,my_wrapper
知道哪些电话是必需的,但我真的不知道这是一起去的最佳方法,并赞赏这样的评论,以及:
而不是以前的类型转换操作符的使用以下两种:
operator T*() & {
return m_ptr;
}
operator T*() &&{
//Do something
return m_ptr;
}
现在operator T*() &&
用的std ::移动和operator T*() &
打电话时被称为没有它调用时被调用。
您是指在呼叫站点还是被调用者区分? –
被调用者的意思是'my_impl'类型? – ZivS
用户的期望是不合理的。如果你对某个东西调用了'std :: move',并将它传递给一个没有占用移动对象的函数,那么期望这个对象是空的或者更改是不合理的。例如:'std :: shared_ptr foo; ... std :: move(foo) - > bar();'这不应该改变'foo',因为'bar'不占有。如果'bar(std :: move(foo));'也是如此。 'std :: move'只是给被调用的函数*权限*来移动对象,如果没有指定它,它不会强制它移动它。 –