代码之家  ›  专栏  ›  技术社区  ›  PierreBdR

C++中的“自动”类代理

  •  2
  • PierreBdR  · 技术社区  · 16 年前

    我需要允许用户同时更改同一类型的两个数据结构的成员。例如:

    struct Foo { int a, b; }
    
    Foo a1 = {1,2}, a2 = {3,4};
    dual(a1,a2)->a = 5;
    // Now a1 = {5,2} and a2 = {5,2}
    

    • 班级很小
    • 用户不介意复制所有内容,而不仅仅是修改部分。

    dual(a1,a2)->a = 5;
    // Now a1 = {5,2} and a2 = {5,4}
    

    我对其他语法持开放态度,但它们应该保持简单,我希望避免以下情况:

    set_members(a1, a2, &Foo::a, 5);
    members(a1, a2, &Foo::a) = 5;
    

    或者任何涉及明确说明的事情 &Foo::

    [编辑]

    G.edge(v1,v2)->b = 5; // Only v1->v2 is modified
    G.arc(v1,v2)->a = 10;
    // Now G.edge(v2,v1) is set to G.edge(v1,v2) after the modification a = 10 (i.e. b = 5 too)
    

    我只想让符号暗示 a

    5 回复  |  直到 16 年前
        1
  •  2
  •   scjohnno    16 年前

    #include <boost/lambda/lambda.hpp>
    
    using namespace boost::lambda;
    
    template<typename T, typename U, typename V>
    void dual(const T& functor, U& a1, V& a2)
    {
        functor(a1);
        functor(a2);
    }
    
    struct Foo
    {
        int a;
    };
    
    struct Bar
    {
        char a;
    };
    
    int main()
    {
        Foo a1;
        Bar a2;
    
        dual(_1 = 5, a1.a, a2.a);
    }
    

    使用可变模板扩展dual()/预处理器恶作剧留给读者作为练习。

        2
  •  2
  •   Alsk    16 年前

    //获取所需的语法

    template<class T>
    class SetPropertyProxy
    {
    public:
       SetPropertyProxy(T& _v1, T& _v2)
         : a(_v1, _v2) {}
    
       class A_Property_Proxy
       {
       public:
           A_Property_Proxy(T& _v1, T& _v2): v1(_v1), v2(_v2) {}
           A_Property_Proxy& operator = (T::A_Property_Type val)
           {
               v1.a = val;
               v2.a = val;
               return *this;
           }
       private:
           T& v1;
           T& v2;
       }
       //public member "a"
       A_Property_Proxy a;
    };
    //helper function
    template<class T>
    SetPropertyProxy<T> dual(T& a , T& b)
    { return SetPropertyProxy<T>(a,b); }
    //usage
    dual(a,b).a = 5; //calls A_Property_Proxy::operator =
    

       template<class U>
       class Property_Proxy
       {
       public:
           Property_Proxy(U& _v1prop, U& _v2prop): v1prop(_v1prop), v2prop(_v2prop) {}
           Property_Proxy& operator = (U val)
           {
               v1prop = val;
               v2prop = val;
               return *this;
           }
       private:
           U& v1prop;
           U& v2prop;
       }
    
        3
  •  0
  •   egrunin    16 年前

    编辑 (放在这里是因为注释没有格式)

    你是说你现在的代码有很多这样的东西:

    G.edge(v3,v4)->a = 2;
    G.edge(v3,v4)->b = 2;
    G.edge(v4,v5)->a = 6;
    G.edge(v4,v5)->b = 6;
    

    G.edge(v5,v6)->a = 4;
    G.edge(v5,v6)->b = 7;
    

    ----- 原来的答案,现在可能无关紧要了-----

    总的来说,有很多可能的改进:

    class MagicBag
    {
    private:
        // you could make the whole class a template 
        // instead of hard-coding Foo..
        vector<Foo *> m_vec;
    
    public:
        // store references to the items
        void Add(Foo *f) { m_vec->push_back(f); }
    
        // you can do overloads instead of these setters...
        void set_a(int val) {
            for (vector<Foo>::iterator i = m_vec.start(); i != m_vec.end(); ++i)
                (*i)->a = val;
        }
    
        void set_b(int val) {
            for (vector<Foo>::iterator i = m_vec.start(); i != m_vec.end(); ++i)
                (*i)->b = val;
        }
    }
    

    用法:

    Foo a1 = {1,2}, a2 = {3,4};
    MagicBag mb;
    
    mb.Add(&a1);
    mb.Add(&a2);
    mb.set_a(5); // now a1.a = 5 and a2.a = 5
    // etc.
    

    在支持属性的语言(如C#)中,这在语义上更容易实现。最后的语法是:

    mb.a = 5;
    
        4
  •  0
  •   Winston Ewert    16 年前

    通过对模板的滥用,我可以得到所需的大部分语法。这是编译和工作,但没有保证它。它需要在要使用的结构中添加一些宏,并且需要使用set\而不是直接赋值。

    #include <iostream>
    
    #define PROPERTY_MAP(ClassName) \
        struct hidden_Mapper {      \
            ClassName * m_d1;       \
            ClassName * m_d2;       \
            hidden_Mapper(Data * d1, Data * d2) : \
                m_d1(d1), m_d2(d2) {} 
    
    #define DECLARE_PROPERTY(name)\
        template <typename ValueType> \
        void set_##name(const ValueType & value) \
        { m_d1->name = value; m_d2->name = value; } \
    
    #define END_PROPERTY_MAP };
    
    
    template<typename ClassType>
    typename ClassType::hidden_Mapper dual(ClassType & d1, ClassType & d2)
    {
        return typename ClassType::hidden_Mapper(&d1, &d2);
    }
    
    struct Data
    {
        int a;
        float b;
    
        PROPERTY_MAP(Data)
            DECLARE_PROPERTY(a)
            DECLARE_PROPERTY(b);
        END_PROPERTY_MAP
    };
    
    int main()
    {
        Data d1, d2;
        dual(d1, d2).set_a(5);
        dual(d1, d2).set_b(5.7);
        std::cout << d1.a << d2.a << d1.b << d2.b <<std::endl;
    }
    
        5
  •  -1
  •   Anycorn    16 年前
    struct proxy {
      struct column {
         column(T &a, T &b);
         column& operator=(T);
         T &a, &b;
      };
      proxy(U &A, U &B);
      column operator[](int i) { return column(A[i], B[i]; }
      U &A, &B;
    };
    
    proxy(A, B)[0] = 5;
    // or you could be evil, overload ",", and get this syntax
    (A, B)[0] = 5;
    

    或者某种变化