Friday 27 February 2015

Snippet: Class Properties in C++11

Update: I discovered several bugs with the initial implementation, so I've updated this post with a more complete solution.

Properties as seen in Python and C# are a pretty nice language feature, they allow you to have the syntax of accessing a public member variable, yet have that access still go through a getter or setter function.

I have to say I'm not totally sold on RW properties (I feel that if you are intending to change the state of a class, you should be forced to make it clear by calling a setter function) but I like RO properties, they remove the need to call a function to just access a value, and still allow you to check pre/post conditions or log access.

C++ doesn't have properties, if you Google around there's a general consensus that they don't fit the language well. However, I got a bit tired of my game engine's API having an excessive number of function calls. Here's an example:

TextureID rtt = window().new_texture(false);
window().mesh(rect_mesh)->set_texture_on_material(0, rtt);

It would be far nicer to be able to write:

TextureID rtt = window->new_texture(false);
window->mesh(rect_mesh)->set_texture_on_material(0, rtt);

... and still have the control that a getter function provides. So I wrote a Property template class, it looks like this..

template<typename Container, typename T>
class Property {
public:
    Property(Container* _this, T Container::* member):
        this_(_this),
        getter_([member](Container* self) -> T& {
            return self->*member;
        }) {
    }

    Property(Container* _this, T* Container::* member):
        this_(_this),
        getter_([member](Container* self) -> T& {
            return *(self->*member);
        }) {
    }

    Property(Container* _this, std::shared_ptr<T> Container::* member):
        this_(_this),
        getter_([member](Container* self) -> T& {
            return *(self->*member);
        }) {
    }

    Property(Container* _this, std::function<T& (Container*)> getter):
        this_(_this),
        getter_(getter) {

    }

    /*
     *  We can't allow copy construction, because 'this_' will never be initialized
     */
    Property(const Property& rhs) = delete;

    Property operator=(const Property& rhs) {
        assert(this_); //Make sure that this_ was initialized

        getter_ = rhs.getter_;
        // Intentionally don't transfer 'this_'
    }

    inline operator T&() const { return getter_(this_); }
    inline T* operator->() const { return &getter_(this_); }
private:
    Container* this_ = nullptr;
    std::function<T& (Container*)> getter_;
};



Container is the class you are adding the property to, T is the type of the property.

Thanks to C++11 allowing initialization of members in the body of the class, and the awesome syntax of lambdas, we can use the Property template like so:

Property<WindowBase, Watcher> watcher = {
    this, [](const WindowBase* self) -> Watcher& {
        if(!self->watcher_) {
            throw LogicError("Watcher has not been initialized");
        } else {
            return *self->watcher_.get();
        }
    }
};

Or, if you just want to wrap a member variable:

Property<WindowBase, Console> console = { this, &WindowBase::console_ };

Unfortunately we can't override the '.' operator in C++ so we can't get the exact same syntax as C# or Python, but the -> operator is good enough (and as a lot of my engine's accessors return pointers, it actually made things more consistent).

13 comments:

  1. An offer is here for you for free fibromyalgia diet plan.

    ReplyDelete
  2. Different classes posts are here for you. I am also a developer and i can easily understand everything which they provide here. I want to be just stay here where you people can must be show law essay help uk work here and then i help them to bring many changes if your work needed.

    ReplyDelete
  3. C+ language is difficult to learn. Overall learning coding needs much energy and time. I buy dissertation online because I have enrolled in a c+ language course. And I didn't get time for writing a dissertation.

    ReplyDelete
  4. Thanks for the article. it was really helpful and I truly appreciate it. tpe manufacturer Visit the website and learn more about TPE and TPR materials, and manufacturing.

    ReplyDelete
  5. buy cheap assignment online buyassignmentservice.com Having the adaptability to assist an extensive choice of topics, we are confident to provide your necessities flawlessly

    ReplyDelete
  6. In C++11, class properties can be declared using the auto keyword. This makes it possible to declare properties without having to specify their type explicitly. Instead, the type is inferred from the value that is assigned to the property.

    Read more: UC Berkeley School of Law: All You Need to Know

    For example, suppose we have a class Person with a property name that is of type string. We can declare this property using the auto keyword as follows:

    class Person {
    public:
    auto name = std::string{};
    };

    In this example, the type of the name property is inferred from the std::string{} value that is assigned to it. This makes it easy to declare properties without having to write out their type explicitly.

    One thing to keep in mind when using class properties in C++11 is that they are not compatible with older versions of the C++ standard. If you need to write code that is compatible with older versions of C++, you will need to declare your properties using the traditional method.

    Overall, class properties in C++11 can be a useful tool for simplifying the declaration of properties in your code. If you need help with implementing class properties or any other C++11 features, reach out to AccessPrep, a leading provider of C++ development services.

    ReplyDelete
  7. we have incredible flutes for sale cheap in Ireland. do visit us and place your order now.

    ReplyDelete
  8. famous movie leather jackets are now available at PLJ in very affordable prices. they have huge collection of bombers, bikers, varsity jackets and much more.

    ReplyDelete
  9. Get forcejackets at 15% off this Valentines day and make the day super special for your partner.If came prints is your vibe than you must check out force leather jackets.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Our service is user-friendly, efficient, and free. You just need to upload your PDF, choose your output format, and download your Word file. Our service will maintain the original quality and appearance of your PDF. Try our service today and discover the power of PDF to Word conversion.
    Visit: https://pdftoword.id/

    ReplyDelete
  12. We offer quality, originality, and affordability for our clients. We also provide free revisions, plagiarism reports, and 24/7 support. Contact us today and get your CIPD assignment done by CIPD Experts.
    cipd assignment help 5co01

    ReplyDelete
  13. You can order your jacket online from the Pelle Pelle website, or visit one of the Pelle Pelle stores in New York, Los Angeles, or Chicago.
    Pelle Pelle coat

    ReplyDelete