Thread: Cannot access protected member declared in X

  1. #1
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

    Cannot access protected member declared in X

    I'll be blunt.
    I don't know why this is happening or how to solve it.
    I don't remember running into such problems before.

    Code snippet:
    Code:
    	template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
    	{
    		if (rhs == *this)
    			return *this;
    		DecRefCount(m_ptr);
    		m_ptr = rhs.m_ptr;
    		IncRefCount(m_ptr);
    		return *this;
    	}
    And error would be:
    Error 1 error C2248: 'mad_shared_ptr<T>::m_ptr' : cannot access protected member declared in class 'mad_shared_ptr<T>'
    In clear words: it's saying I don't have permission to access rhs.m_ptr which is declared as protected inside mad_shared_ptr<T>.

    Error line in red, of course.
    Ideas? Suggestions?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #2
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    they're different template types so they're different class types.

    template<typename Other> friend class mad_shared_ptr;

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I suppose a minimal example would be something like this?

    Code:
    template <class T>
    class X
    {
        protected:
            int x;
        public:
            template <class U>
            X& operator= (const X<U>& rhv)
            {
                x = rhv.x;
                return *this;
            }
    };
    
    int main()
    {
        X<int> x;
        X<float> y;
        y = x;
    }
    X<int> and X<float> are different classes which I suppose aren't meant to have access to each others' internals?

    I guess the friend keyword can help to make different X's friends of each other.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Anon's example is more correct. A little more snippet:
    Code:
    template<typename T, ...> class mad_shared_ptr
    {
    public:
    	template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
    	{
    		if (rhs == *this)
    			return *this;
    		DecRefCount(m_ptr);
    		m_ptr = rhs.m_ptr;
    		IncRefCount(m_ptr);
    		return *this;
    	}
    
    protected:
    	sptr<T, Bits>* m_ptr;
    };
    As I think the small snippet says, it's a shared pointer, so it makes sense to be able to assign a derived class to a base class. Hence the Other template operator =.
    I already know that they are of different types (ie mad_shared_ptr<T> vs mad_shared_ptr<Other>), so usually they aren't allowed access, but... in this case, the friend keyword isn't going to help, is it? Because mad_shared_ptr<Other> would have to add a friend declaration for mad_shared_ptr<T>.

    I want (or need to) do this, essentially:
    mad_shared_ptr<Derived> p1(...);
    mad_shared_ptr<Base> p2(p1);

    The question is: how do I do it in this case?

    EDIT:
    Digging through boost's shared_ptr, I find this:
    Code:
        template<class Y>
        explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
        {
            // it is now safe to copy r.px, as pn(r.pn) did not throw
            px = r.px;
        }
    Albeit this is in a constructor.
    Are there special rules for constructors being able to access members of another type?
    Last edited by Elysia; 01-11-2010 at 03:23 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    At the end of the shared_ptr class, there is

    Code:
    // Tasteless as this may seem, making all members public allows member templates
    // to work in the absence of member template friends. (Matthew Langston)
    
    #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
    
    private:
    
        template<class Y> friend class shared_ptr;
        template<class Y> friend class weak_ptr;
    
    
    #endif
    
        T * px;                     // contained pointer
        boost::detail::shared_count pn;    // reference counter
    So these members are either public, or shared_ptrs and weak_ptrs are all friends to each other.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    When I'm designing a template that needs to be able to access the internals of itself when instantiated on different types, I usually do that by inheriting from a non-template base and putting the "generic" stuff in there, as opposed to declaring all instantiations to be friends of each other.

    Code:
    class shared_ptr_base
    {
    protected:
        // nothing is public, only derived classes can access
    };
    
    template < typename T >
    class shared_ptr : public shared_ptr_base
    {
    };
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Does your mad_shared_ptr<T> class have an operator=( const mad_shared_ptr<T>& rhs ) function? I would think that would be all you need since Other is derived from T...
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by anon View Post
    At the end of the shared_ptr class, there is

    Code:
    // Tasteless as this may seem, making all members public allows member templates
    // to work in the absence of member template friends. (Matthew Langston)
    
    #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
    
    private:
    
        template<class Y> friend class shared_ptr;
        template<class Y> friend class weak_ptr;
    
    
    #endif
    
        T * px;                     // contained pointer
        boost::detail::shared_count pn;    // reference counter
    So these members are either public, or shared_ptrs and weak_ptrs are all friends to each other.
    Hmmm.
    Yet, I cannot get this to work, at least not with the 3 parameters I have:
    Code:
    template<typename Other> friend class mad_shared_ptr<T, thread_safety, Bits>;
    error C3772: 'mad_shared_ptr<T,thread_safety,Bits>' : invalid friend template declaration
    Code:
    template<typename Other> friend class mad_shared_ptr;
    error C2976: 'mad_shared_ptr' : too few template arguments
    Would it work with one parameter? I would need to test, I think.

    Quote Originally Posted by brewbuck View Post
    When I'm designing a template that needs to be able to access the internals of itself when instantiated on different types, I usually do that by inheriting from a non-template base and putting the "generic" stuff in there, as opposed to declaring all instantiations to be friends of each other.

    Code:
    class shared_ptr_base
    {
    protected:
        // nothing is public, only derived classes can access
    };
    
    template < typename T >
    class shared_ptr : public shared_ptr_base
    {
    };
    That is an interesting solution, albeit I'm not quite how to fit this into this smart pointer.
    The code needs access to rhs.m_ptr. How do I get this with such a code? All the inherited members from the class in rhs would be unavailable to me.
    I would need to declare the smart pointers as friends, yet this leads to anon's suggested solution which I cannot get to work...

    Quote Originally Posted by cpjust View Post
    Does your mad_shared_ptr<T> class have an operator=( const mad_shared_ptr<T>& rhs ) function? I would think that would be all you need since Other is derived from T...
    Other does not necessarily need to be derived from T. We will rely on the compiler for that. If T and Other are unrelated, we would get a compiler error saying it cannot convert Other* to T*.
    Anyway, yes I do have it, but no, it doesn't work properly.

    Code:
    	mad_shared_ptr& operator = (const mad_shared_ptr& rhs)
    	{
    		return operator = <T>(rhs);
    		// Calls template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs).
    	}
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Let me guess, you're trying to declare partial specialisations as friends. A weakness in the current standard is you can't do that.

    The closest you can come to is something like this;
    Code:
    template <class A, class B, class C> class mad_shared_ptr
    {
         // your other stuff
    
         private:
    
              template<class Alpha, class Bravo, class Charlie> friend class X;
    };
    The down side of this is that it means all instantiations of the template class X are friends of each other - there is no narrowing down to a subset of possible instantatiations of the template as friends.

    For example, you can't replace the friend declaration above with
    Code:
     template<class Alpha, class Bravo> friend class X<Alpha, Bravo, C>;
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by grumpy View Post
    Let me guess, you're trying to declare partial specialisations as friends. A weakness in the current standard is you can't do that.
    So I noticed.

    The closest you can come to is something like this;
    But ah, if this works, then I may have learned another quirk in the language.
    I will try this out when I get back home. Thanks.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    It's a bit of a hack, but it seems to work fine (on gcc, at least):

    Code:
    
    template < typename Type >	
    class test
    {				
    	public:
    	
    	template < typename Other >
    	test& operator = ( test< Other > const& rhs )
    	{
    		value = get_member( rhs );
    		return *this;
    	}	
    
    	protected:
    
    	friend Type const& get_member( test const& rhs )
    	{
    		return rhs.value;
    	}
    		
    	Type
    		value;	
    };	
    
    int main( void )
    {
    	test< float >
    		tf;
    	test< int >
    		ti;
    	tf = ti;	
    }

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Grumpy's solution seemed to work. So case closed on this one.
    Thanks.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Similar problem again, so I'm bumping this.
    Example:
    Code:
    template<int> class dummy {};
    template<typename T, template<int> class Unused1 = dummy, int Unused2 = 0> class test
    {
    public:
    	typedef test<T, Unused1, Unused2> me_t;
    	test(T* p): m_p(p) {}
    	template<typename rhs_t> test& operator = (const rhs_t& rhs) { m_p = rhs.m_p; }
    	template<typename rhs_t> bool friend operator == (const me_t& lhs, const rhs_t& rhs)
    	{
    		return (lhs.m_p == rhs.m_p);
    	}
    protected:
    	//int m_SomeProtectedMember;
    	T* m_p;
    	template<typename, template<int> class, int> friend class test;
    };
    
    class A {};
    class B: public A {};
    
    int main()
    {
    	test<A> pA = new A();
    	test<B> pB = new B();
    	pA = pB;
    	pA == pB;
    }
    1>g:\application data2\visual studio 2008\projects\test\test.cpp(146) : error C2248: 'test<T>::m_p' : cannot access protected member declared in class 'test<T>'
    1> with
    1> [
    1> T=B
    1> ]
    1> g:\application data2\visual studio 2008\projects\test\test.cpp(150) : see declaration of 'test<T>::m_p'
    1> with
    1> [
    1> T=B
    1> ]
    1> g:\application data2\visual studio 2008\projects\test\test.cpp(162) : see reference to function template instantiation 'bool operator ==<test<T>>(const test<A> &,const rhs_t &)' being compiled
    1> with
    1> [
    1> T=B,
    1> rhs_t=test<B>
    1> ]
    What is the usual solution to such a problem?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Perhaps delegate to a member function for comparing.

    Code:
    	template<typename rhs_t> bool friend operator == (const me_t& lhs, const rhs_t& rhs)
    	{
    		return lhs.equals(rhs);
    	}
    
            template<typename rhs_t>
    	bool equals(const rhs_t& rhs) const { return m_p == rhs.m_p; }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    This one works. Anyone know why I don't have access to rhs in the free operator =, though?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 11
    Last Post: 05-02-2009, 09:23 AM
  2. cannot access private member declared in class
    By newme in forum C++ Programming
    Replies: 7
    Last Post: 11-16-2008, 03:57 PM
  3. Access protected base class template variable
    By pjotr in forum C++ Programming
    Replies: 4
    Last Post: 11-06-2007, 05:34 AM
  4. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  5. Replies: 3
    Last Post: 03-22-2005, 03:27 AM