필자는 사용자에게 제공하는 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;
}
[이것은 당연히 사건의 예에 불과하고, 래퍼 더 많은 방법이 있습니다,하지만 난 여기에 역할을하지 않는 확신 해요 : 여기 어떻게 생겼는지의 예 이 경우]
사용자는 래퍼에서 std :: move가 호출 된 다음 foo
을 호출 한 후 래퍼가 비어 있거나 적어도 이동 된 것처럼 수정 될 것으로 예상합니다. , 실제로는 foo
전에 호출되는 유일한 메소드가 캐스트 연산자입니다.
foo
에 대한 호출을 foo
의 두 호출 사이에서 구별 할 수있는 방법이 있습니까? 즉 std::move
을 사용하거나 사용하지 않고 전화 할 때입니까? 음매 오리의 의견에
편집 덕분에 나는 my_wrapper
가 요구되는 통화 알고있는 방법을 발견,하지만 난이 갈 수있는 가장 좋은 방법입니다뿐만 아니라이에 대한 의견을 주셔서 감사합니다 정말 확실하지 않다 : 대신 이전 캐스트 연산자의
는 다음과 같은 두 가지 사용없이 호출 할 때 표준 : 이동 및 operator T*() &
로 호출 할 때 지금 operator T*() &&
를 호출
operator T*() & {
return m_ptr;
}
operator T*() &&{
//Do something
return m_ptr;
}
가 호출됩니다.
호출 사이트 또는 수신자가 구별 할 수 있습니까? –
피 호출자는'my_impl' 타입을 의미합니까? – ZivS
사용자의 기대치가 부당합니다. 무언가에'std :: move'를 호출하고 이동 된 객체를 소유하지 않는 함수로 전달하면, 객체가 비어 있거나 변경 될 것이라고 기대하는 것은 무리입니다. 예 :'std :: shared_ptr foo; ... std :: move (foo) -> bar();'bar가 소유하지 않기 때문에'foo'를 변경해서는 안됩니다. 'bar (std :: move (foo));'와 같은 경우. 'std :: move'는 객체를 움직이기 위해 호출 된 함수 * 권한 *을 주지만, 그것이 지정되지 않았다면 강제로 움직이지 않습니다. –