Search code examples
c++boostboost-preprocessor

How to hide a field via define and provide only setter and getter?


I wonder how to hide a real property field (not make it private or public but force to use setters and getters) and provide him with simple setter and getter. So I wonder how to create api like:

private:
    Property( int my_a);
public:
    Property( int my_b);
...
{
 set_my_a(1);
 cout << get_my_a() << endl;
 // my_a = 13; // will cause compiler error
...

How to create such thing via Boost preprocessor?


Solution

  • Do you really need to use boost preprocessor? you have a solution without boost below:

    // property.h    
    #include <stdio.h>
    
    #define property(type) struct : public Property <type>  
    
    template <typename T>
    class Property 
    {
    protected:
      T value;
    public:
      virtual T get() { 
        return value; 
      }
      virtual void set(T new_value) { 
        value = new_value; 
      }
    };
    

    usage example:

    // test.cpp
    #include "property.h"
    
    class Test {
    public:
      property(int) {} a;
    
      property(int)  {
        int get() { 
          return value * 10; 
        } 
      } b;
    
      property(int) {
        void set(int x) {
          value = x * 200;
        } 
      } c;
    
      property(int) {
        int get() { 
          return value * 3000; 
        } 
        void set(int x) {
          value = x * 443;
        } 
      } d;
    };
    
    main()
    {
      Test t;
    
      printf("i\ta\tb\tc\td\t\n");
      for (int i=0; i<10; i++) { 
        t.a.set(i);
        t.b.set(i);
        t.c.set(i);
        t.d.set(i);
        printf("%i\t%i\t%i\t%i\t%i\n", i, t.a.get(), t.b.get(), t.c.get(), t.d.get());
      }
    }
    

    The wikipedia solution in http://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B is good but needs a minimal modification to become useful, because without the protected statement you cant write your own getters and setters.

    #include <iostream>
    
    template <typename T> 
    class property {
    protected:
      T value;
    public:
      T & operator = (const T &i) {
        ::std::cout << i << ::std::endl;
        return value = i;
      }
      operator T const & () const {
        return value;
      }
    };
    
    struct Bar {
      property <bool> alpha;
      struct :public property <int> {
        int & operator = (const int &i) {
          ::std::cout << "new setter " << i << ::std::endl;
          return value = i;
        }
      } bravo;
    };
    
    main() 
    {
      Bar b;
      b.alpha = false;
      b.bravo = (unsigned int) 1;
    }
    

    You can change a little more if you want:

    #include <iostream>
    #define SETTER(type) public: type& operator=(const type new_value)
    #define GETTER(type) public: operator type const & () const
    
    template <typename T> 
    class Property {
    protected:
      T value;
    public:
      T & operator = (const T &i) {
        ::std::cout << i << ::std::endl;
        return value = i;
      }
      template <typename T2> T2 & operator = (const T2 &i) {
        ::std::cout << "T2: " << i << ::std::endl;
        T2 &guard = value;
        throw guard; // Never reached.
      }
      operator T const & () const {
        return value;
      }
    };
    
    struct Bar {
      Property <bool> alpha;
      struct:Property <int> {
        SETTER(int) {
          value = new_value * 1000;
          ::std::cout << "new method " << new_value << ::std::endl;
          return value;
        }
        GETTER(int) {
          return value/1000;
        }
      } bravo;
    };
    
    main() 
    {
      Bar b;
      b.alpha = false;
      b.bravo = (unsigned int) 1;
      ::std::cout << b.bravo << ::std::endl;
    }