2016-06-08 11 views
5

포인터로 구현하는 관용구를 사용하여 변경 불가능한 객체에 데코레이터 패턴을 구현하고 있습니다. 기본적으로 내 설정이 여기에이개체가 구성원 함수 내에서 일시적인지 여부를 감지 할 수 있습니까?

struct Object : ObjectBase { 
    void doSmth() override { 
     impl->doSmth(); 
    } 
    // this is the function I'd like to implement 
    Object decorateWith(std::unique_ptr<ObjectDecorator>&&); 
private: 
    std::unique_ptr<ObjectBase> impl; 
}; 

struct ObjectDecorator : ObjectBase { 
    void doSmth() override { 
     // do some stuff 
     impl->doSmth(); 
     // do some more stuff 
    } 
private: 
    std::unique_ptr<ObjectBase> impl; 
}; 

처럼 보인다는 decorateWith 기능이 켜져 캘런하고있는 객체 임시 여부를 인 여부에 따라 다른 동작을 할 예정이다. 비 임시 객체에서 호출되는 경우 현재 객체의 전체 복사본을 만들어 데코레이터의 unique_ptr에 저장해야하는 새 Object 인스턴스를 반환해야합니다. 반면 새 Object 자체의 impl 포인터 데코레이터를 가리키고 있습니다. 그러나 decorateWith가 임시로 호출되면 ObjectDecorator를 만들고 현재 객체의 impl-pointer를 데코레이터의 impl 포인터로 이동하고 객체가 새 데코레이터를 가리 키도록 만 충분합니다.

decoreWith를 호출 할 때 객체가 임시 객체인지 여부를 결정할 수있는 방법이 필요하다는 사실을 깨닫고 해당 검사 결과를 기반으로 태그 전달을 사용하십시오. 그게 가능하니?

최저 Xodion

편집 : 샘플 발신자 코드는 다음과 같을 수 있습니다 :

  • decorateWith 임시에 호출되는 비 일시적

    int main() { 
        Object x{}; 
    
        // this call does not modify x so it can be reused later 
        Object y = x.decorateWith{std::make_unique<ObjectDecorator>()}; 
        y.doSmth(); 
    
        // do some other stuff here 
    
        // here, if I had moved the impl-unique_ptr in the decorateWith 
        // call this would now segfault since I'd call nullptr->doSmth(); 
        x.doSmth(); 
    
    } 
    
  • decorateWith에서 호출

    int main() { 
        Object x = Object{}.decorateWith(std::make_unique<ObjectDecorator>()) 
             .decorateWith(std::make_unique<ObjectDecorator>()) 
             .decorateWith(std::make_unique<ObjectDecorator>()); 
        // in this case it would be unneccessary to make a deep copy of all 
        // previous instances so I'd like to only move the impl poiner every time 
        x.doSmth() 
    } 
    
+1

샘플 호출 코드를 사용하면 설명이 더 잘 백업 될 수 있습니다. – kfsone

+2

'decorateWith'가'decorateWith'를 호출 한 것이 임시인지,'decorateWith'의 인수가 임시인지를 묻는 중입니까? – md5i

+0

decorateWith가 호출 된 객체가 임시 객체 일 때만 조건부로 이동하려고합니다. 따라서 객체가 임시 객체인지 확인하는 방법에 관한 것입니다. 아래의 해답에서 알 수 있듯이 ref-qualifier를 사용하여 오버로드 할 수 있기 때문에 일종의 유형 특성이 필요하지 않습니다. – Corristo

답변

12

회원 기능에 ref 한정자를 사용할 수 있습니다. 상황에 따라서 en.cppreference.com

#include <iostream> 
struct S { 
    void f() & { std::cout << "lvalue\n"; } 
    void f() &&{ std::cout << "rvalue\n"; } 
}; 

int main(){ 
    S s; 
    s.f();   // prints "lvalue" 
    std::move(s).f(); // prints "rvalue" 
    S().f();   // prints "rvalue" 
} 

에서 복사 예를 들어, 당신은 당신이 const를 사용하려는 방식과 유사 멤버 함수를 오버로드 참조 한정자를 사용할 수있는이

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &; 
Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &&; 
+0

그렇습니다. 그럼에도 불구하고 ref-qualifier가 필요한 것입니다. – Corristo

4

같은 것을 갖고 싶어 것 const 및 비 const 개체에 대한 과부하 :

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) const& 
{ 
    // implementation if this is not a temporary 
} 

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) && 
{ 
    // implementation if this IS a temporary 
} 
2

예. 다음과 같은 두 가지 방법을 구현하는 경우 : *this이를 rvalue 경우

Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &; 
Object decorateWith(std::unique_ptr<ObjectDecorator>&&) &&; 

두 번째 호출됩니다.