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