[sword-devel] non-proprietary property mechanism

Troy A. Griffitts sword-devel@crosswire.org
Thu, 06 Jan 2000 02:45:11 -0700


Well, per our discussion, I believe we are close to a non-proprietary
implementation of Borland's propery mechanism.  This was my response
with a working example.  Let me know comments and suggestions.

__________________________

      Subject: Re:
        Date: Thu, 06 Jan 2000 02:31:39 -0700
        From: "Troy A. Griffitts" <scribe@crosswire.org>
Organization: CrossWire Bible Society
          To: Bjarne Stroustrup
  References: 
             1


Bjarne,
        Thank you for your kind response.  I added parameterized getters
and
setters.  The result follows:


// class TTreeView {
//   TTreeNodes* FTreeNodes;
//   __property TTreeNodes* Items = {read=FTreeNodes,
write=SetTreeNodes};
//   void SetTreeNodes(TTreeNodes* Value);
// };

#include<iostream>
using namespace std;


template<class Context, class T>
     class property {
          Context* view;  // an Item needs to access values in its
context
          T (Context::*Getter)();
          void (Context::*Setter)(T);

     public:

          property(Context* v, T (Context::*G)(), void (Context::*S)(T))
:view(v), Getter(G), Setter(S) { }

          operator T() { return (view->*Getter)(); }    // assume get()
function          T operator->() { return (view->*Getter)(); }  //
assume ste() function
          property& operator=(T Value) { (view->*Setter)(Value); return
*this; }     };


struct TTreeNodes {
     int val;
     TTreeNodes* next;
     TTreeNodes() :val(0), next(0) { }
     void Clear() { cout << "clear\n"; val = 0; }
     TTreeNodes* Next() { return next; }
};


class TTreeView {
     TTreeNodes* n;

public:

     void set(TTreeNodes* Value) { cout <<"set\n"; n = Value; }
     TTreeNodes* get() { return n; }

     property<TTreeView,TTreeNodes*> Items;    // items of type
TTreenodes* in a TTreeview

     TTreeView() :Items(this, &get, &set) { n = new TTreeNodes(); }   
// give Items their context

};


int main()
{
     TTreeView* treeView = new TTreeView();
     TTreeNodes treeElements;

     treeView->Items->Clear();
     treeView->Items = &treeElements;

     for (TTreeNodes *i = treeView->Items; i; i = i->Next()) {
          cout << i->val << endl;
     }

     return 0;
}



The operator ->() was unexpected, I figured it would imply a cast to the
compiler.  Would a second property template for nonpointers with an
operator .() be appropriate?

I first tried a syntax like:

template<class Context, class T, T (Context::*R)(), void
(Context::*W)(T)>

hoping it would allow:
     property<TTreeView, TTreeNodes*, &TTreeView::get, &TTreeView::set>
Items;

This template passed g++ compile, but not the usage of it.  The compiler
stated that TTreeView had no member get nor set.



> I think a crucial design decision is how to parameterize _Item on
> the set() and get() functions.

The former way works and is fairly readable, but it would be nice to
keep everything logically related to the property in the header file.


> Your turn! (for comments, suggestions, problems, etc.)

Thanks again.  Your guidance has been indescribably valuable.  I also 
understand you must be very busy.


God is a God of extremes:  Never did anyone have so much, give it up so
completely, to die such a death, all for such an enemy as me. 
-Philippians 2:5-8; Romans 5:6-10

[P2:5. Det samme Sindelag være i eder, som også var i Kristus Jesus,  6.
han, som, da han var i Guds Skikkelse ikke holdt det for et Rov at være
Gud lig,  7. men forringede sig selv, idet han tog en Tjeners Skikkelse
på og blev Mennesker lig;  8. og da han i Fremtræden fandtes som et
Menneske, fornedrede han sig selv, så han blev lydig indtil Døden, ja,
Korsdøden.]

[R 5:6. Thi medens vi endnu vare kraftesløse, døde Kristus til den
bestemte Tid for ugudelige.  7. Næppe vil nemlig nogen dø for en
retfærdig-for den gode var der jo måske nogen, som tog sig på at dø-, 
8. men Gud beviser sin Kærlighed over for os, ved at Kristus døde for
os, medens vi endnu vare Syndere.  9. Så meget mere skulle vi altså, da
vi nu ere blevne retfærdiggjorte ved hans Blod, frelses ved ham fra
Vreden.  10. Thi når vi, da vi vare Fjender, bleve forligte med Gud ved
hans Søns Død, da skulle vi meget mere, efter at vi ere blevne forligte,
frelses ved hans Liv]

        -Troy.

http://www.crosswire.org/sword/