Appleshell
Appleshell

Reputation: 7388

How to implement generic accessors for property class

How would generic accessors for a property class and their defaults be implemented?

I roughly think it would look as follows:

template<typename Type, 
         typename Getter = /* How to implement a default setter? */
         typename Setter = 
class Property {
    Getter get; /* Is this right? How is it called then? */
    Setter set;

    Property(Type value, Getter getter, Setter setter) ...
};

Getter and Setter should be able to be given as lambdas. Is this the right approach, and how do I continue?

Upvotes: 1

Views: 1044

Answers (2)

Kerrek SB
Kerrek SB

Reputation: 477228

You could agree to some kind of structural interface for getters and setters, and then implement something like this:

template <typename T> struct default_getter
{
    T & operator()(T & x) const { return x; }
    T const & operator()(T const & x) const { return x; }
};

template <typename T> struct default_setter
{
    template <typename U>
    void operator()(T & x, U && u) const { x = std::forward<U>(u); }
};

template <typename T,
          typename Getter = default_getter<T>,
          typename Setter = default_setter<T>>
class Property
{
    struct PropertyImpl : Getter, Setter
    { 
         T value;
    };

    PropertyImpl impl;
public:
    template <typename U>
    void set(U && u)
    {
        static_cast<Setter &>(impl)(impl.value, std::forward<U>(u));
    }

    T & get()
    {
        static_cast<Getter &>(impl)(impl.value);
    }

    T const & get() const 
    {
        static_cast<Getter const &>(impl)(impl.value);
    }
};

Now you can use it like so:

struct Foo
{
    Property<Bar> bar;
};

Foo x;
x.bar.get();
x.bar.set(10);

Upvotes: 1

Sebastian Hoffmann
Sebastian Hoffmann

Reputation: 11502

I would propose a solution using std::function.

template<typename T>
struct Property
{
   typedef std::function<T()> GetterFunc;
   typedef std::function<void(const T&)> SetterFunc;

   Property (T value, GetterFunc getter, SetterFunc setter) 
   : m_getter(getter)
   , m_setter(setter) 
   {
   }

   Property(T value) 
   : m_getter( [value](){ return value; }
   , m_setter ( [](const T&) { } ) // I have know clue what behaviour you want here
   {
   }

   T Get() { return m_getter(); }
   void Set(const T& value) { m_setter(value); }

private:

    GetterFunc m_getter;
    SetterFunc m_setter;
} 

Upvotes: 0

Related Questions