Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ avoiding code duplication for const and non-const visitation

I have a class that should call a visitor method for every member variable. Something like this:

class A{
    int a, b, c;

public:
    void accept(Visitor &visitor){
        visitor.visit(a);
        visitor.visit(b);
        visitor.visit(c);
    }
};

How can I get void accept() const method with the same code without code duplication?

The obvious solution with the duplication is to add a method:

void accept(Visitor &visitor) const {
    visitor.visit(a);
    visitor.visit(b);
    visitor.visit(c);
}

That method has exactly the meaning I want, but I would like to avoid the code duplication. The reason to have both methods is to be able to read the variables by a 'reading' visitor and having the accept method nicely const. Then the non-const accept would be possible to use for 'writing/updating' visitors.

like image 387
Juraj Blaho Avatar asked Mar 09 '11 21:03

Juraj Blaho


2 Answers

You could create a class static template helper function that will deduce the constness based on the type of the this pointer you provide to it. Like this:

class A{
    int a, b, c;

public:

    void accept(Visitor &visitor){
        acceptImpl(*this, visitor);
    }
    void accept(Visitor &visitor) const{
        acceptImpl(*this, visitor);
    }

private:
    template<typename t_A>
    static void acceptImpl(t_A& aObj, Visitor &visitor)
    {
        visitor.visit(aObj.a);
        visitor.visit(aObj.b);
        visitor.visit(aObj.c);
    }
};
like image 142
zdan Avatar answered Oct 14 '22 19:10

zdan


Template helper:

class A{
    int a, b, c;

private:
    template <typename T>
    static void do_visiting(T &self, Visitor &visitor) {
        visitor.visit(self.a);
        visitor.visit(self.b);
        visitor.visit(self.c);
    }
public:
    void accept(Visitor &visitor) {
        do_visiting(*this, visitor); // calls do_visiting<A>
    }
    void accept(Visitor &visitor) const {
        do_visiting(*this, visitor); // calls do_visiting<const A>
    }
};
like image 38
Steve Jessop Avatar answered Oct 14 '22 19:10

Steve Jessop