Hello fellow developers,

yesterday, I was thinking about how to implement specific config.
attributes accessors in section-based nut config. files so that
it's nice to use and consistent with NutConfiguration, UpsmonConfiguration
and UpsdConfiguration config. classes (where it's done via Settable attributes).

The GenericConfiguration class provides generic access to name/value
items of config. sections. The specialised classes (like e.g. UpsConfiguration)
shall inherit the mechanism from GenericConfiguration and are supposed to
provide specialised (and typed) access to the config. attributes.
Now, the obvious choice is to write getters/setters for them; however,
this way, the access will be different than access to section-less config.
files attributes.
What I came with is a template class (see "redirect" in the sample code 
attached)
that overloads the cast operator and the assignment operator (and possibly 
others)
and therefore gives the user the possibility to execute code (the 
getters/setters)
while the code looks just like r/w access to a variable (with certain 
restrictions, though).

Now, the mechanism looks kind of cool, but is also a bit technically complex,
not to mention that it's disputable whether such masking of code execution
is a good idea.  I can imagine that it can be quite confusing for an outsider...
So, do you think that it's worth it or should I better keep the code less 
"smart"
but more simple (now, when I'm writing that, it seems to answer itself...)?

Thanks for the consult,

Regards,

--
Václav Krpec
Network UPS Tools project
Eaton Opensource Team




-----------------------------
Eaton Elektrotechnika s.r.o. ~ S�dlo spolecnosti, jak je zaps�no v rejstr�ku: 
Kom�rovsk� 2406, Praha 9 - Horn� Pocernice, 193 00, Cesk� Republika ~ Jm�no, 
m�sto, kde byla spolecnost zaregistrov�na: Praha ~ Identifikacn� c�slo (ICO): 
498 11 894 
-----------------------------

#include <string>
#include <iostream>
#include <vector>
#include <sstream>

/** Redirection */
template <typename T, typename R, typename read_hook, typename write_hook>
class redirect {
    private:

    R &        m_obj;    /**< Object       */
    read_hook  m_rhook;  /**< Reading hook */
    write_hook m_whook;  /**< Writing hook */

    public:

    /** Constructor */
    redirect(R & obj): m_obj(obj) {}

    /** Reading */
    inline operator T() {
        return m_rhook(m_obj);
    }

    /** Writing */
    inline T operator = (const T & rval) {
        return m_whook(m_obj, rval);
    }

};  // end of template class redirect


/** A generic class */
class Gen {
    private:

    std::vector<std::string> m_vals;

    public:

    /** Constructor */
    Gen() {
        m_vals.reserve(3);

        m_vals.push_back("123");
        m_vals.push_back("456");
        m_vals.push_back("789");
    }

    /** Generic getter */
    inline std::string getVal(size_t index) const {
        std::cout << "getVal(" << index << ") called" << std::endl;

        if (index < m_vals.size())
            return m_vals[index];

        return "";
    }

    /** Generic setter */
    inline void setVal(size_t index, const std::string & val) {
        std::cout << "setVal(" << index << ", \"" << val << "\") called" << 
std::endl;

        if (index < m_vals.size())
            m_vals[index] = val;
    }

};  // end of class Gen


/** A specific class */
class Spec: private Gen {
    private:

    /** Value reading hook */
    template <size_t index>
    class rval {
        public:

        int operator () (Gen & gen) {
            int val;

            std::stringstream ss(gen.getVal(index));

            ss >> val;

            return val;
        }

    };  // end of template class rval

    /** Value writing hook */
    template <size_t index>
    class wval {
        public:

        int operator () (Gen & gen, int val) {
            std::stringstream ss;

            ss << val;

            gen.setVal(index, ss.str());

            return val;
        }

    };  // end of template class wval

    public:

    redirect<int, Gen, rval<0>, wval<0> > val1;  /**< Redirected attr */
    redirect<int, Gen, rval<1>, wval<1> > val2;  /**< Redirected attr */
    redirect<int, Gen, rval<2>, wval<2> > val3;  /**< Redirected attr */

    Spec(): val1(*this), val2(*this), val3(*this) {}

};  // end of class Spec


int main() {
    Spec s;

    std::cout << "Reading val2..." << std::endl;

    int val2 = s.val2;

    std::cout << "Result: " << val2 << std::endl;

    std::cout << "Writing val3..." << std::endl;

    s.val3 = 654;

    std::cout << "Done" << std::endl;

    std::cout << "Checking val3..." << std::endl;

    bool ok = 654 == s.val3;

    std::cout << "Result: " << ok << std::endl;

    return 0;
}
_______________________________________________
Nut-upsdev mailing list
Nut-upsdev@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev

Reply via email to