C++ Template friend odd behavior -


i'm seeing can't explain in following code. under vs6, vs9, , gcc t2::foo2() gives error: 'bar' : cannot access protected member declared in class 'c1'. if remove c1::bar(), compiles , runs correctly, though t2 still accessing protected c1b:bar(), think same problem.

note, in t2::foo2() cast 'pt1' 't1*' , fine, still not explain why c1b::bar() allowed, c1::bar() not.

template<class s> class t2;  template<class t> class t1 {     //template<class t> friend class t2;  --> doesn't compile under vs6     friend class t2<t>;      protected:         virtual void bar() { printf("t1\n"); } };  template<class s> class t2 {     public:         void foo1(t1<s> *pt1) { pt1->bar(); }  // --> ok, makes sense, works either way         void foo2(s *pt1) { pt1->bar(); }  // --> fails compile if c1::bar() defined, works c1b::foo() ??? };  class c1 : public t1<c1> {     protected:         virtual void bar() { printf("c1\n"); }  // --> comment out , foo2 compile };  class c1b : public  c1 {     protected:         virtual void bar() { printf("c1b\n"); } };  class c2 : public  t2<c1> { };  void test(void) {     c1b c1b;     c2 c2;     c2.foo1(&c1b);     c2.foo2(&c1b);  // --> fails compile if c1::bar() exists } 

in example, type of parameter s in foo2 c1. friend relationship exists between t2<s> , t1<s>. although c1 derives t1<c1> not become friend of friends of t1<c1>.

in expression pt1->bar, bar found in c1 and, friendship not passed down derived class, private.

your example using virtual functions can addressed explicitly referring bar is friend of our class:

void foo2(s *pt1) { pt1->template t1<s>::bar(); } 

the access check succeeds.

the reference in '03 c++ standard in 11.4/10, says:

friendship neither inherited nor transitive.

thanks potatoswatter comment. using qualified-id id-expession, disable virtual dispatch (5.2.2/1):

if selected function non-virtual, or if id-expression in class member access expression qualified-id, function called.

we can add non-virtual dispatcher, or can first convert parameter base type , make call:

 void foo2(s *pt1) { static_cast< t1<s>* > (pt1)->bar(); } 

virtual dispatch takes place required.


Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -