make member functions (in)accessible

Dear all, I'm trying to find some magic that makes a member function of some object x accessible if and only if it were called from within a class that has object x as a member. Is there a (boost)-way of doing this? As this may seem a bit obscure, I'm trying to give an example: template <typename T, bool Writable> class Property { public: T get() const; void set(const T& val); private: T m_val; }; is a simple class holding a value of T. I have some classes holding potentially many Properties. I'd like to have these properties publically available, some as only readable, others writable as well, so that others (e.g. gui-classes) can access them: class A { public: Property<double, true > propA; Property<int , false> propB; }; so I may do: A a; a.propA.get(); a.propA.set(0.5); a.propB.get(); but NOT: a.propB.set(1); because propB was defined with Writable=false. BUT, from within class A, I would like to do propB.set(1); because otherwise this property is useless. (How) can this be achieved (with boost)? I could make set() private in the Writable=false - specialisation of Property and declare A as a friend, but that's prohibitive since Property shouldn't know about A and it won't work for derived classes of A. Another option would be class A { public: A() : propA(propA_priv), propB(propB_priv) {} PropertyWrapper<double, true > propA; PropertyWrapper<int , false> propB; private: Property<double> propA_priv; Property<int > propB_priv; }; so the actual properties are private and the wrapper provides the actual interface to the outside world. But as there may be many properties I'd like to get away without the wrapper objects ... Thanks for any ideas! Stefan

Though I have not used it myself, there is enable_if or disable_if in BOOST. That might help. -dhruva ----- Original Message ----
From: Stefan Funck <stefanfunck@web.de> To: boost-users@lists.boost.org Sent: Thursday, 26 February, 2009 7:34:01 PM Subject: [Boost-users] make member functions (in)accessible
Dear all,
I'm trying to find some magic that makes a member function of some object x accessible if and only if it were called from within a class that has object x as a member. Is there a (boost)-way of doing this?
As this may seem a bit obscure, I'm trying to give an example:
template class Property { public: T get() const; void set(const T& val); private: T m_val; }; is a simple class holding a value of T.
I have some classes holding potentially many Properties. I'd like to have these properties publically available, some as only readable, others writable as well, so that others (e.g. gui-classes) can access them:
class A { public: Property propA; Property propB; };
so I may do:
A a; a.propA.get(); a.propA.set(0.5); a.propB.get();
but NOT:
a.propB.set(1);
because propB was defined with Writable=false. BUT, from within class A, I would like to do
propB.set(1);
because otherwise this property is useless. (How) can this be achieved (with boost)?
I could make set() private in the Writable=false - specialisation of Property and declare A as a friend, but that's prohibitive since Property shouldn't know about A and it won't work for derived classes of A. Another option would be
class A { public: A() : propA(propA_priv), propB(propB_priv) {}
PropertyWrapper propA; PropertyWrapper propB; private: Property propA_priv; Property propB_priv; };
so the actual properties are private and the wrapper provides the actual interface to the outside world. But as there may be many properties I'd like to get away without the wrapper objects ...
Thanks for any ideas! Stefan
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Add more friends to your messenger and enjoy! Go to http://messenger.yahoo.com/invite/

AMDG Stefan Funck wrote:
so I may do:
A a; a.propA.get(); a.propA.set(0.5); a.propB.get();
but NOT:
a.propB.set(1);
because propB was defined with Writable=false. BUT, from within class A, I would like to do
propB.set(1);
because otherwise this property is useless. (How) can this be achieved (with boost)?
These two cases are indistinguishable. In Christ, Steven Watanabe

At 10:11 AM 2/26/2009, you wrote:
AMDG Stefan Funck wrote:
so I may do:
A a; a.propA.get(); a.propA.set(0.5); a.propB.get();
but NOT:
a.propB.set(1);
because propB was defined with Writable=false. BUT, from within class A, I would like to do
propB.set(1);
because otherwise this property is useless. (How) can this be achieved (with boost)?
These two cases are indistinguishable.
Are they? While we seem to have wandered off the Boost territories, consider this: If B (== typeof(propB)) were defined effectively as class B { public: void get(...); private: void set(...); friend class A; }; would that not have the effect desired? Conceptually you could use the CRTP pattern to mix A in to the instantiation of propB so that only A was a friend. I don't think you can do this in real life with templates because gcc does not allow declaring template parameters as friends (e.g., this does not compile) template < typename T > class X { friend T; };

These two cases are indistinguishable.
Are they? While we seem to have wandered off the Boost territories, consider this: If B (== typeof(propB)) were defined effectively as
class B { public: void get(...); private: void set(...); friend class A; };
would that not have the effect desired? Conceptually you could use the CRTP pattern to mix A in to the instantiation of propB so that only A was a friend.
I don't think you can do this in real life with templates because gcc does not allow declaring template parameters as friends (e.g., this does not compile)
template < typename T > class X { friend T; };
I would suggest using something similar as a "password type". Tested with MSVC 9 #include <boost/type_traits/is_same.hpp> #include <boost/utility/enable_if.hpp> #include <iostream> template<class Type, class PasswordT=void> class Property { public: Type const& get()const { return value_; } template<class PwdT> void set( Type const& value) { set_impl<PwdT, PasswordT>(value); } void set(Type const& value) { set_impl<void, PasswordT>(value); } private: template<class Pwd, class ExpectedPwd> void set_impl( Type const& value , typename boost::enable_if<boost::is_same<Pwd, ExpectedPwd> >::type* enable =0 ) { value_ = value; } private: Type value_; }; class A { private: struct secret {}; public: Property<int> test1; Property<long, secret> test2; void set_via_a(long l) { test2.set<secret>(l); } }; int main() { A a; a.test1.set(10); //a.test2.set(20); //ERROR a.set_via_a(20); using namespace std; cout << "test1: " << a.test1.get() << "\ntest2: " << a.test2.get(); return 0; } Hope that helps, Ovanes

private: template<class Pwd, class ExpectedPwd> void set_impl( Type const& value , typename boost::enable_if<boost::is_same<Pwd, ExpectedPwd> >::type* enable =0 ) { value_ = value; }
Actually ExpectedPwd is not required as template parameter, but it helps to understand the flow. It is possible to rewrite the Property as: template<class Type, class PasswordT=void> class Property { public: Type const& get()const { return value_; } template<class PwdT> void set( Type const& value) { set_impl<PwdT>(value); } void set(Type const& value) { set_impl<void>(value); } private: template<class Pwd> void set_impl( Type const& value , typename boost::enable_if<boost::is_same<Pwd, PasswordT>
::type* enable =0 ) { value_ = value; }
private: Type value_; };
participants (5)
-
Alan M. Carroll
-
dhruva
-
Ovanes Markarian
-
Stefan Funck
-
Steven Watanabe