2016-04-23 11 views
0

this articleにいくつかの素敵なプロパティテンプレートがあります。テンプレートを関数呼び出しポインタで使用して完全転送する

私は彼らが完璧な転送をサポートしたいのですが、私は私の現在のソリューションが好きではありません:指定された右辺値セッター(コメントアウト)なし

// test type that logs constructor, destructor and assignment operator calls 
struct TestType { 

    TestType() { trace("[", this, "] constructor"); } 
    ~TestType() { trace("[", this, "] destructor"); } 

    TestType(const TestType& other) { 
     trace("[", this, "] copy constructor copying ", other); 
    } 

    TestType& operator=(const TestType& other) { 
     debug("[", this, "] copy assignment operator"); 
     TestType temporary(other); 
     trace("[", this, "] swap data with ", temporary); 
     return *this; 
    } 

    TestType& operator=(TestType&& other) { 
     debug("[", this, "] move assignment operator"); 
     trace("[", this, "] swap data with ", other); 
     return *this; 
    } 
}; 

// << operator for TestType 
std::ostream& operator<<(std::ostream& output, const TestType& value) { 
    return (output << "[" << &value << "]"); 
} 

// test object containing an UnrestrictedProperty with custom getter and setter methods 
class TestObject { 

    TestType internal_value; 

    const TestType& get_value() const { 
     return internal_value; 
    } 
    const TestType& set_value(const TestType& value) { 
     return (internal_value = value); 
    } 
    const TestType& set_value(TestType&& value) { 
     return (internal_value = std::move(value)); 
    } 

public: 

    // create an UnrestrictedProperty for a TestType value-type in the TestObject class 
    UnrestrictedProperty<TestType, TestObject, &TestObject::get_value, &TestObject::set_value/*, &TestObject::set_value*/> value; 
    // (the thrid (commented out) function pointer is the rvalue version of the setter) 

    TestObject() { 
     // tell the value property on which object instance it should call the getter and setter methods 
     value(this); 
    } 

}; 

void test() { 

    print("property test starts"); 
    { 
     print("creating object"); 
     TestObject object; 

     print("assigning object.value with rvalue"); 
     { 
      object.value = TestType(); 
     } 

     print("assigning object.value with lvalue"); 
     { 
      TestType local = TestType(); 
      object.value = local; 
     } 

     print("leaving objects scope"); 
    } 
    print("property test ends"); 

} 

出力:

// a read-write property which invokes user-defined functions 
template <class Type, class Object, const Type&(Object::*real_getter)() const, const Type&(Object::*real_setter)(const Type&), const Type&(Object::*real_mover)(Type&&) = nullptr> 
class UnrestrictedProperty { 
    Object* object; 
public: 
    UnrestrictedProperty(Object* owner_object = nullptr) : object(owner_object) {} 

    // initializer to specify the owner 
    void operator()(Object* owner_object) { 
     this->object = owner_object; 
    } 

    // function call syntax 
    const Type& operator()() const { 
     return (object->*real_getter)(); 
    } 
    const Type& operator()(const Type& value) { 
     return (object->*real_setter)(value); 
    } 
    const Type& operator()(Type&& value) { 
     if (real_mover) return (object->*real_mover)(std::forward<Type>(value)); 
     return (object->*real_setter)(value); 
    } 

    // get/set syntax 
    const Type& get() const { 
     return (object->*real_getter)(); 
    } 
    const Type& set(const Type& value) { 
     return (object->*real_setter)(value); 
    } 
    const Type& set(Type&& value) { 
     if (real_mover) return (object->*real_mover)(std::forward<Type>(value)); 
     return (object->*real_setter)(value); 
    } 

    // access with '=' sign 
    operator const Type&() const { 
     return (object->*real_getter)(); 
    } 
    const Type& operator=(const Type& value) { 
     return (object->*real_setter)(value); 
    } 
    const Type& operator=(Type&& value) { 
     if (real_mover) return (object->*real_mover)(std::forward<Type>(value)); 
     return (object->*real_setter)(value); 
    } 

    // comparators 
    bool operator==(const Type& value) const { 
     return get() == value; 
    } 
    bool operator!=(const Type& value) const { 
     return not operator==(value); 
    } 

    // might be useful for template deductions 
    typedef Type value_type; 
}; 

// << operator for UnrestrictedProperty 
template <class Type, class Object, const Type&(Object::*real_getter)() const, const Type&(Object::*real_setter)(const Type&), const Type&(Object::*real_mover)(Type&&)> 
std::ostream& operator<<(std::ostream& output, const UnrestrictedProperty<Type, Object, real_getter, real_setter, real_mover> unrestricted_property) { 
    return (output << unrestricted_property.get()); 
} 

使い方を:指定された右辺値セッターと

 
    [ ] property test starts 
    [ ] creating object 
    [T] [0026F22C] constructor 
    [ ] assigning object.value with rvalue 
    [T] [0026F157] constructor 
    [D] [0026F22C] copy assignment operator 
    [T] [0026EF43] copy constructor copying [0026F157] 
    [T] [0026F22C] swap data with [0026EF43] 
    [T] [0026EF43] destructor 
    [T] [0026F157] destructor 
    [ ] assigning object.value with lvalue 
    [T] [0026F223] constructor 
    [D] [0026F22C] copy assignment operator 
    [T] [0026EF43] copy constructor copying [0026F223] 
    [T] [0026F22C] swap data with [0026EF43] 
    [T] [0026EF43] destructor 
    [T] [0026F223] destructor 
    [ ] leaving objects scope 
    [T] [0026F22C] destructor 
    [ ] property test ends 

出力:

 
    [ ] property test starts 
    [ ] create object 
    [T] [0015F7EC] constructor 
    [ ] assign object.value with rvalue 
    [T] [0015F717] constructor 
    [D] [0015F7EC] move assignment operator 
    [T] [0015F7EC] swap data with [0015F717] 
    [T] [0015F717] destructor 
    [ ] assign object.value with lvalue 
    [T] [0015F7E3] constructor 
    [D] [0015F7EC] copy assignment operator 
    [T] [0015F503] copy constructor copying [0015F7E3] 
    [T] [0015F7EC] swap data with [0015F503] 
    [T] [0015F503] destructor 
    [T] [0015F7E3] destructor 
    [ ] leaving objects scope 
    [T] [0015F7EC] destructor 
    [ ] property test ends 

そう...

意図したとおりに機能しますが、私は別に右辺値セッターのポインタを渡す必要があり、ヌルのために右辺値が渡されるたびに、それをチェックする必要があります。

提案がありますか?

答えて

0

タイプは、タイプTの値に割り当てる操作まで消去されます。それをassign_to<T>と呼んでください。

あなたの予想されるセッターは、そのタイプをとってください。

これは、その部分(r vs l)を複数の方法で移動させます。タイプ消しゴムはちょっとした仕事ですが、一度だけ書きます。

template<class T> 
struct assign_to { 
    std::function<void(T&)> op; 
    assign_to(T const & t):op([&t](T& dest){dest=t;}){} 
    assign_to(T&& t):op([&t](T& dest){dest=std::move(t);}){} 
    assign_to(assign_to&&)=default{} 
    void write(T& t){ op(t); } 
}; 
関連する問題