T
tkamin
The C++ standards (98, 03, 11) in section $5.3.1/3 defines that in
situation:
struct Base { int a; };
struct Derived : Base {};
The expression &Derived::a will return pointer of type int Base::*
instead of int Derived::*.
This solution causes some suprisings problems in code code that seem
to be perfectly valid.
1. Multiple indirect inheritance from one Base class, example;
struct Very_base { int a; };
struct Base1 : Very_base {};
struct Base2 : Very_base {};
struct Derived : Base1, Base2 {}
int main() {
Derived d;
d.Base1::a; //omit dis-ambiguity by explicit qualification as
defined in $10.1/5
d.Base2::a; //omit dis-ambiguity by explicit qualification as
defined in $10.1/5
&Derived::Base1::a; //Valid, yields int Very_base::*
&Derived::Base2::a; //Valid, yields int Very_base::*
int Derived:: * a_ptr = &Derived::Base1::a; //yields an error about
Very_base being ambiguous base class of Derived despite the
qualification
};
2. Problem with pointer to member pointer arguments. Lets assume that
we have:
struct Base { int a; };
struct Derived : Base { int b; };
//Member access generator to use with libraries that allows function
pointers only
template<typename Class, typename Member_type, Member_type Base:: *
ptr>
Member_type get(Class &c) { return c.*ptr; }
void call(int (*f)(Derived &));
int main()
{
call(&get<Derived, int, &Derived::b>); //Works correctly
call(&get<Derived, int, &Derived::a>); //Not working because
&Derived::a returns an int Base::* and no conversions are applied to
pointer to member (as specified in $14.3.2/5)
call(&get<Base, int, &Derived::a>); //Template function is
instantiated properly but has incompatible
}
3. Private inheritance:
struct Base { int a; };
struct Derived : private Base
{
public:
using Base::a; //make a accessible
};
int main()
{
Derived d;
d.a; //valid
&Derived::a; //Valid, Derived::a is accessible at this poin
int Derived::* ptr = &Derived::a; //Conversion from int Base::* to
int Derived::* is illegal because the base class is inaccessible as
defined in $4.11/2
}
None of this problems will occure if the expression &class::member
would always return decltype(class::member) class::* pointer.
Was there any reason for specifing this expression to return pointer
to base class in some situation?
situation:
struct Base { int a; };
struct Derived : Base {};
The expression &Derived::a will return pointer of type int Base::*
instead of int Derived::*.
This solution causes some suprisings problems in code code that seem
to be perfectly valid.
1. Multiple indirect inheritance from one Base class, example;
struct Very_base { int a; };
struct Base1 : Very_base {};
struct Base2 : Very_base {};
struct Derived : Base1, Base2 {}
int main() {
Derived d;
d.Base1::a; //omit dis-ambiguity by explicit qualification as
defined in $10.1/5
d.Base2::a; //omit dis-ambiguity by explicit qualification as
defined in $10.1/5
&Derived::Base1::a; //Valid, yields int Very_base::*
&Derived::Base2::a; //Valid, yields int Very_base::*
int Derived:: * a_ptr = &Derived::Base1::a; //yields an error about
Very_base being ambiguous base class of Derived despite the
qualification
};
2. Problem with pointer to member pointer arguments. Lets assume that
we have:
struct Base { int a; };
struct Derived : Base { int b; };
//Member access generator to use with libraries that allows function
pointers only
template<typename Class, typename Member_type, Member_type Base:: *
ptr>
Member_type get(Class &c) { return c.*ptr; }
void call(int (*f)(Derived &));
int main()
{
call(&get<Derived, int, &Derived::b>); //Works correctly
call(&get<Derived, int, &Derived::a>); //Not working because
&Derived::a returns an int Base::* and no conversions are applied to
pointer to member (as specified in $14.3.2/5)
call(&get<Base, int, &Derived::a>); //Template function is
instantiated properly but has incompatible
}
3. Private inheritance:
struct Base { int a; };
struct Derived : private Base
{
public:
using Base::a; //make a accessible
};
int main()
{
Derived d;
d.a; //valid
&Derived::a; //Valid, Derived::a is accessible at this poin
int Derived::* ptr = &Derived::a; //Conversion from int Base::* to
int Derived::* is illegal because the base class is inaccessible as
defined in $4.11/2
}
None of this problems will occure if the expression &class::member
would always return decltype(class::member) class::* pointer.
Was there any reason for specifing this expression to return pointer
to base class in some situation?