Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Overloads resolution crazyness ?

Overloads resolution crazyness ?

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++questionregextutorial
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Marcello
    wrote on last edited by
    #1

    Hello, a question around the error C2666, under vc80 (RTM-8.0.50727.4200) Is it compliant to the C++ standard ? class CondParams { ... static bool getVariableState( const string& s, int& idx, string::size_type* p = NULL; // A static bool getVariableState( string& rs, int& idxVar, const bool& trim ); // B ); bool CondParams::getVariableState( string& rs, int& idx, const bool& trim ) { ... VCF::String::size_type p = 0; bool ok = getVariableState( rs, idx, &p ); if ( ok ) rs = rs.substr( p ); ... } I get the error message: 1>d:\projs\condparams.cpp(66) : error C2666: 'vcfex::CondParams::getVariableState' : 2 overloads have similar conversions 1> d:\projs\code\condparams.h(130): could be 'bool vcfex::CondParams::getVariableState(string &,int &,const bool &)' 1> d:\projs\code\condparams.h(129): or 'bool vcfex::CondParams::getVariableState(const string &,int &,string::size_type *)' 1> while trying to match the argument list '(string, int, size_type *)' 1> note: qualification adjustment (const/volatile) may be causing the ambiguity I could fix the problem by doing: 1) static bool getVariableState( string& s, int& idx, string::size_type* p = NULL; // A or by doing: 2) bool ok = getVariableState( const_cast(rs), idx, &p ); so I guess that the compiler is confused because it doesn't find any perfect match. The solution 1 is usually not acceptable. So I have to apply 2). But this situation is *very* common: why should I need to specify that a variable is constant each time I am using it as argument for a function that declared that is not going to modify it ? Also it doesn't logically seem necessary. It is like the Standard C++ ( or Microsoft? ) is forcing me to put a const_cast everywhere. This was not a problem with vc70. Similar issue, but not identical, with an example given in vc80 RTM help about the C2666 error. enum E { E_A, E_B }; class A { int h(const E e) const {return 0; } int h(const int i) { return 1; } // Uncomment the following line to resolve. // int h(const E e) { return 0; } void Test() { h(E_A); // C2666 h((const int) E_A); h((int) E_A); } }; Why the compiler shouldn't be smart enough to understand that int h(const E e) is a better match than int h(const int i) ? Why in earth int h(const E e) solves the problem, while int h(const E e) co

    R 1 Reply Last reply
    0
    • M Marcello

      Hello, a question around the error C2666, under vc80 (RTM-8.0.50727.4200) Is it compliant to the C++ standard ? class CondParams { ... static bool getVariableState( const string& s, int& idx, string::size_type* p = NULL; // A static bool getVariableState( string& rs, int& idxVar, const bool& trim ); // B ); bool CondParams::getVariableState( string& rs, int& idx, const bool& trim ) { ... VCF::String::size_type p = 0; bool ok = getVariableState( rs, idx, &p ); if ( ok ) rs = rs.substr( p ); ... } I get the error message: 1>d:\projs\condparams.cpp(66) : error C2666: 'vcfex::CondParams::getVariableState' : 2 overloads have similar conversions 1> d:\projs\code\condparams.h(130): could be 'bool vcfex::CondParams::getVariableState(string &,int &,const bool &)' 1> d:\projs\code\condparams.h(129): or 'bool vcfex::CondParams::getVariableState(const string &,int &,string::size_type *)' 1> while trying to match the argument list '(string, int, size_type *)' 1> note: qualification adjustment (const/volatile) may be causing the ambiguity I could fix the problem by doing: 1) static bool getVariableState( string& s, int& idx, string::size_type* p = NULL; // A or by doing: 2) bool ok = getVariableState( const_cast(rs), idx, &p ); so I guess that the compiler is confused because it doesn't find any perfect match. The solution 1 is usually not acceptable. So I have to apply 2). But this situation is *very* common: why should I need to specify that a variable is constant each time I am using it as argument for a function that declared that is not going to modify it ? Also it doesn't logically seem necessary. It is like the Standard C++ ( or Microsoft? ) is forcing me to put a const_cast everywhere. This was not a problem with vc70. Similar issue, but not identical, with an example given in vc80 RTM help about the C2666 error. enum E { E_A, E_B }; class A { int h(const E e) const {return 0; } int h(const int i) { return 1; } // Uncomment the following line to resolve. // int h(const E e) { return 0; } void Test() { h(E_A); // C2666 h((const int) E_A); h((int) E_A); } }; Why the compiler shouldn't be smart enough to understand that int h(const E e) is a better match than int h(const int i) ? Why in earth int h(const E e) solves the problem, while int h(const E e) co

      R Offline
      R Offline
      Ryan Binns
      wrote on last edited by
      #2

      For the first situation... VCF::String::size_type and string::size_type are not the same type, so neither of the function calls match perfectly. However, both could match using implicit casting rules, hence the ambiguity. If you intend to call the first one, make sure the parameter is string::size_type rather than VCF::String::size_type For the second situation... Again, neither overload matches perfectly. You're calling a function called h from a non-const this pointer. The compiler can either implicitly convert this to a const pointer and call the first one, or it can implicitly convert E to an int and call the second one. Neither conversion has preference over the other, so there is an ambiguity. The reason uncommenting the other definition of h works is because it is a perfect match to the function call - there is no conversion required.

      Ryan

      "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

      M 1 Reply Last reply
      0
      • R Ryan Binns

        For the first situation... VCF::String::size_type and string::size_type are not the same type, so neither of the function calls match perfectly. However, both could match using implicit casting rules, hence the ambiguity. If you intend to call the first one, make sure the parameter is string::size_type rather than VCF::String::size_type For the second situation... Again, neither overload matches perfectly. You're calling a function called h from a non-const this pointer. The compiler can either implicitly convert this to a const pointer and call the first one, or it can implicitly convert E to an int and call the second one. Neither conversion has preference over the other, so there is an ambiguity. The reason uncommenting the other definition of h works is because it is a perfect match to the function call - there is no conversion required.

        Ryan

        "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

        M Offline
        M Offline
        Marcello
        wrote on last edited by
        #3

        Thank you very much for the reply. Please forget about the VCF::String thing. It was a typo on my side. Here is a code I made for this question ( it compiles class Cond { public: typedef std::basic_string MyString; Cond() { }; virtual ~Cond(void) { }; Cond( const Cond& other ) { /* simple implementation just for this example */ *this = other; }; Cond& operator= ( const Cond& other ) { return *this; }; // implementation bool split( const MyString& s, MyString::size_type* p = NULL ); bool split( MyString& s, const bool& trim ); }; inline bool Cond::split( const MyString& s, MyString::size_type* p ) { /* simple implementation just for this example */ return true; } inline bool Cond::split( MyString& s, const bool& trim ) { MyString::size_type p; //if ( split( const_cast(s), &p ) ) // this compiles fine if ( split( s, &p ) ) // C2666 { s = s.substr( p + 1 ); return true; } return false; } I get the error message: 1>d:\projs\libraries\vcfex\src\conditions\test.h(51) : error C2666: 'vcfex::Cond::split' : 2 overloads have similar conversions 1> d:\projs\libraries\vcfex\src\conditions\test.h(37): could be 'bool vcfex::Cond::split(vcfex::Cond::MyString &,const bool &)' 1> d:\projs\libraries\vcfex\src\conditions\test.h(36): or 'bool vcfex::Cond::split(const vcfex::Cond::MyString &,stlp_std::basic_string<_CharT,_Traits,_Alloc>::size_type *)' 1> with 1> [ 1> _CharT=wchar_t, 1> _Traits=stlp_std::char_traits, 1> _Alloc=stlp_std::allocator 1> ] 1> while trying to match the argument list '(vcfex::Cond::MyString, stlp_std::basic_string<_CharT,_Traits,_Alloc>::size_type *)' 1> with 1> [ 1> _CharT=wchar_t, 1> _Traits=stlp_std::char_traits, 1> _Alloc=stlp_std::allocator 1> ] 1> note: qualification adjustment (const/volatile) may be causing the ambiguity It puzzles me that the C++ standard ( or is just vc80 ? ) is asking me to specify const_cast when intuitively the compiler should resolve the two overloads 'without effort'. A comment on this after the next point. I understand what you say at the second point. I agree but I am really surprised at the same time. I always considered a const function just as a way to tell the compler that that function is not going to change the 'this' pointer. So I ca

        R 1 Reply Last reply
        0
        • M Marcello

          Thank you very much for the reply. Please forget about the VCF::String thing. It was a typo on my side. Here is a code I made for this question ( it compiles class Cond { public: typedef std::basic_string MyString; Cond() { }; virtual ~Cond(void) { }; Cond( const Cond& other ) { /* simple implementation just for this example */ *this = other; }; Cond& operator= ( const Cond& other ) { return *this; }; // implementation bool split( const MyString& s, MyString::size_type* p = NULL ); bool split( MyString& s, const bool& trim ); }; inline bool Cond::split( const MyString& s, MyString::size_type* p ) { /* simple implementation just for this example */ return true; } inline bool Cond::split( MyString& s, const bool& trim ) { MyString::size_type p; //if ( split( const_cast(s), &p ) ) // this compiles fine if ( split( s, &p ) ) // C2666 { s = s.substr( p + 1 ); return true; } return false; } I get the error message: 1>d:\projs\libraries\vcfex\src\conditions\test.h(51) : error C2666: 'vcfex::Cond::split' : 2 overloads have similar conversions 1> d:\projs\libraries\vcfex\src\conditions\test.h(37): could be 'bool vcfex::Cond::split(vcfex::Cond::MyString &,const bool &)' 1> d:\projs\libraries\vcfex\src\conditions\test.h(36): or 'bool vcfex::Cond::split(const vcfex::Cond::MyString &,stlp_std::basic_string<_CharT,_Traits,_Alloc>::size_type *)' 1> with 1> [ 1> _CharT=wchar_t, 1> _Traits=stlp_std::char_traits, 1> _Alloc=stlp_std::allocator 1> ] 1> while trying to match the argument list '(vcfex::Cond::MyString, stlp_std::basic_string<_CharT,_Traits,_Alloc>::size_type *)' 1> with 1> [ 1> _CharT=wchar_t, 1> _Traits=stlp_std::char_traits, 1> _Alloc=stlp_std::allocator 1> ] 1> note: qualification adjustment (const/volatile) may be causing the ambiguity It puzzles me that the C++ standard ( or is just vc80 ? ) is asking me to specify const_cast when intuitively the compiler should resolve the two overloads 'without effort'. A comment on this after the next point. I understand what you say at the second point. I agree but I am really surprised at the same time. I always considered a const function just as a way to tell the compler that that function is not going to change the 'this' pointer. So I ca

          R Offline
          R Offline
          Ryan Binns
          wrote on last edited by
          #4

          Marcello wrote:

          So at the end it seems that the standard C++ is treating a difference betweenconst and non-const at the same level as a difference between types completelyunrelated. This, even when the the const specifier is just there to tell thatwhat is specified as const will not be changed by the function using that instance

          const isn't just there to portray information to the compiler, it actually changes the type. So char* and const char* are as different (to the compiler) as char* and float. The difference between the two examples is that the compiler has rules for implicity converting between the first pair, but not the second. So const on a function definition doesn't just tell the compiler that the function doesn't modify any of the class members, it also changes the way the compiler handles ambiguity resolution, as you've found out - because the type of the function is different. Incidentally, this is also why you can have two identical function signatures that differ only in their "constness" - they are different types. As for your first point, neither of the functions is an exact match, but both of them can be satisfied by implicit conversion rules, so the call is ambiguous. In this case, the first parameter is a MyString&, which matches the second function but not the first, and the second parameter is a MyString::size_type* which matches the first function, but not the second. However, MyString& can be implicitly converted to const MyString&, and also MyString::size_type* can be implicitly converted to const bool&, and the compiler really has no way of knowing which you intended. It has no choice but to flag the ambiguity. Casting either parameter explicitly should remove the ambiguity. As you have hinted, the VS2005 compiler is much more strict than previous compilers, but it is behaving according to the standard.

          Ryan

          "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups