| |
| /* 1. A standard covnersion sequence is better than a user-defined sequence |
| which is better than an elipses conversion sequence. */ |
| |
| class A{}; |
| class B: public A {public: operator int (){ return 1;}}; |
| |
| // standard vs user-defined |
| int foo0 (int) { return 10; } |
| int foo1 (int) { return 11; } // B -> int : user defined |
| int foo1 (A) { return 12; } // B -> A : standard |
| int test1 () { |
| B b; |
| return foo1(b); // 12 |
| } |
| |
| // user-defined vs ellipsis |
| int foo2 (int) { return 13;} // B -> int : user defined |
| int foo2 (...) { return 14;} // B -> ... : ellipsis |
| int test2(){ |
| B b; |
| return foo2(b); // 13 |
| } |
| |
| /* 2. Standard Conversion squence S1 is better than standard Conversion |
| S2 if: */ |
| |
| // - S1 has a better rank than S2 |
| // see overload.exp for more comprehensive testing of this. |
| int foo3 (double) { return 21; } // float->double is 'promotion rank' |
| int foo3 (int) { return 22; } // float->int is 'conversion rank' |
| int test3(){ |
| return foo3 (1.0f); // 21 |
| } |
| |
| // - S1 and S2 are both 'qualification conversions' but S1 cv-qualification |
| // is a subset of S2 cv-qualification. |
| int foo4 (const volatile int*) { return 23; } |
| int foo4 ( volatile int*) { return 24; } |
| int test4 () { |
| volatile int a = 5; |
| return foo4(&a); // 24 |
| } |
| |
| // - S1 and S2 have the same rank but: |
| // - S2 is a conversion of pointer or memeber-pointer to bool |
| int foo5 (bool) { return 25; } |
| int foo5 (void*) { return 26; } |
| int test5 () { |
| char *a; |
| return foo5(a); // 26 |
| } |
| |
| // - Class B publicly extends class A and S1 is a conversion of |
| // B* to A* and S2 is a conversion B* to void* |
| int foo6 (void*) { return 27; } |
| int foo6 (A*) { return 28; } |
| int test6 () { |
| B *bp; |
| return foo6(bp); // 28 |
| } |
| |
| // - Class C publicly extends Class B which publicly extends |
| // class A and S1 is a conversion of C* to B* and S2 is a |
| // conversion C* to A*. |
| class C: public B {}; |
| int foo7 (A*) { return 29; } |
| int foo7 (B*) { return 210; } |
| int test7 () { |
| C *cp; |
| return foo7(cp); // 210 |
| } |
| |
| // - Same as above but for references. |
| int foo8 (A&) { return 211; } |
| int foo8 (B&) { return 212; } |
| int test8 () { |
| C c; |
| return foo8(c); // 212 |
| } |
| |
| // - Same as above but passing by copy. |
| int foo9 (A) { return 213; } |
| int foo9 (B) { return 214; } |
| int test9 () { |
| C c; |
| return foo9(c); // 212 |
| } |
| |
| // - S1 is a conversion of A::* to B::* and S2 is a conversion of |
| // A::* to C::8. |
| int foo10 (void (C::*)()) { return 215; } |
| int foo10 (void (B::*)()) { return 216; } |
| int test10 () { |
| void (A::*amp)(); |
| return foo10(amp); // 216 |
| } |
| |
| // - S1 is a subsequence of S2 |
| int foo101 (volatile const char*) { return 217; } // array-to-pointer conversion |
| // plus qualification conversion |
| int foo101 ( const char*) { return 218; } // array-to-pointer conversion |
| |
| int test101 () { |
| return foo101("abc"); // 216 |
| } |
| |
| /* 3. User defined conversion U1 is better than user defined Conversion U2, |
| if U1 and U2 are using the same conversion function but U1 has a better |
| second standard conversion sequence than U2. */ |
| class D {public: operator short(){ return 0;}}; |
| int foo11 (float) { return 31; } |
| int foo11 (int) { return 32; } |
| int test11 () { |
| D d; |
| return foo11(d); // 32 |
| } |
| |
| /* 4. Function Level Ranking. |
| All else being equal some functions are preferred by overload resolution. |
| Function F1 is better than function F2 if: */ |
| // - F1 is a non-template function and F2 is a template function |
| template<class T> int foo12(T) { return 41; } |
| int foo12(int) { return 42; } |
| int test12 (){ |
| return foo12(1); //42 |
| } |
| |
| // - F1 is a more specialized template instance |
| template<class T> int foo13(T) { return 43; } |
| template<class T> int foo13(T*) { return 44; } |
| int test13 (){ |
| char *c; |
| return foo13(c); // 44 |
| } |
| |
| // - The context is user defined conversion and F1 has |
| // a better return type than F2 |
| class E { |
| public: |
| operator double () {return 45; } |
| operator int () {return 46; } |
| }; |
| int foo14 (int a) {return a;} |
| int test14 (){ |
| E e; |
| return foo14(e); // 46 |
| } |
| |
| int main() { |
| B b; |
| foo0(b); |
| foo1(b); |
| test1(); |
| |
| foo2(b); |
| test2(); |
| |
| foo3(1.0f); |
| test3(); |
| |
| volatile int a; |
| foo4(&a); |
| test4(); |
| |
| char *c; |
| foo5(c); |
| test5(); |
| |
| B *bp; |
| foo6(bp); |
| test6(); |
| |
| C *cp; |
| foo7(cp); |
| test7(); |
| |
| C co; |
| foo8(co); |
| test8(); |
| |
| foo9(co); |
| test9(); |
| |
| void (A::*amp)(); |
| foo10(amp); |
| test10(); |
| |
| foo101("abc"); |
| test101(); |
| |
| D d; |
| foo11(d); |
| test11(); |
| |
| foo12(1); |
| test12(); |
| |
| foo13(c); |
| test13(); |
| |
| E e; |
| foo14(e); |
| test14(); |
| |
| return 0; // end of main |
| } |