Solved

CString::operator[] ambiguity.

Posted on 1998-08-07
14
1,035 Views
Last Modified: 2013-11-20
I have the following line of code, which causes me trouble:
char charCurrent = strPathName[i];

strPathName is a CString.

It generates this error:
...(156) : error C2666: '[]' : 2 overloads have similar conversions (new behavior; please see help)

Help on "Compiler Error C2666" gave me this:
{
'identifier' : number overloads have similar conversions
The specified overloaded function or operator was ambiguous. If you’ve encountered this error on code which compiled with an earlier version of Visual C++, please read Technote: Improved Conformance to ANSI C++ for more information.
This error is caused by formal parameter lists that are too similar to resolve ambiguity.
An explicit cast of one or more of the actual parameters can resolve the ambiguity.
The following is an example of this error:
 
void func( int, float ) {};
void func( float, int ) {};
func( 1, 1 );        // error, same conversion for each func
func( 1, (float)1 )  // OK
}

CString::operator[] is declared:
TCHAR operator[](int nIndex) const; // same as GetAt

I looked up TCHAR, and it is typedef'd as char.

I know I can use GetAt without problem, but why should I have to?

I only see 1 operator[]. Which "2 overloads" is it talking about? Even if there are more than 1, why would it cause ambiguity? How do I make it not ambiguous?

I've had this problem before in an other class that had a const and non-const operator[]. This doesn't even seem to be the case. What's up?
0
Comment
Question by:TylerRick
  • 5
  • 3
  • 2
  • +2
14 Comments
 
LVL 7

Expert Comment

by:psdavis
ID: 1320421
Here's a sniplet from the class definition.  The real question that I want to know is what is 'i'?  If it is a true 'int', then I would doubt that you would get the error, but you're right, this is a enigma.

char charCurrent = strPathName[i];

class CString
{
public:
// Constructors
      CString();
      CString(const CString& stringSrc);

// Attributes & Operations
      TCHAR GetAt(int nIndex) const;      // 0 based
      TCHAR operator[](int nIndex) const; // same as GetAt
      void SetAt(int nIndex, TCHAR ch);
.
};

Phillilp

0
 
LVL 22

Expert Comment

by:nietod
ID: 1320422
The thing that confuses me is that CString::operator[] is not overloaded.  There aren't two overloads for it to choose between.  Are you sure that strPathName is a CString?  can you post a large code sample?
0
 
LVL 8

Expert Comment

by:trestan
ID: 1320423
In afx.h, [] is declared only once, but in afxcoll.h, this operator is overloaded (pls check it for detail). The stdafx.h include the libs. That is why the error message. To correct it, just explicitly use int or const to cast the index number i. char charCurrent = strPathName[(int)i]; the error should disappear.

0
 

Author Comment

by:TylerRick
ID: 1320424
trestan, I checked afxcoll.h and class CString is not declared there. It is declared in afx.h.
These classes are in afxcoll.h:
class CStringArray;         // array of CStrings
class CStringList;          // list of CStrings
I believe the "coll" means collections, which CString is not.

>The thing that confuses me is that CString::operator[] is not overloaded.
Right, I still believe that there is only 1 CString::operator[]. Don't ask me why. Shouldn't there be a const and non-const, like there is for, say, CStringArray?

>To correct it, just explicitly use int or const to cast the index number i. char charCurrent = strPathName[(int)i]; the error should disappear.
Yes, that worked to get rid of the error message. Thanks for that, trestan.

Sorry I didn't say what i was before. It is:
unsigned short int

I guess that explains it, huh? I guess my problem was that my i (unsigned short int) is not a true "int" (signed short int?) as Phillilp suggested.

But I still would like to know why there is ambiguity if there is only 1 operator[] defined? The error said there were "2 overloads", which, as far as I can tell, there are not! Can some one explain what is going on? Or is the compiler just confused?


0
 
LVL 32

Expert Comment

by:jhance
ID: 1320425
You've got some other problem elsewhere in your code.  The following code compiles OK.  Post your declaration of strPathName.

      CString strPathName;
      strPathName = "Testing";

      for(int i=0; i<5; i++){
            TCHAR charCurrent = strPathName[i];
      }
0
 
LVL 22

Expert Comment

by:nietod
ID: 1320426
Does it work if you make your counter an unsigned short int?  That would be a good test.  
0
 
LVL 22

Expert Comment

by:nietod
ID: 1320427
I tested and I have the same problem with an unsigned short index.


>>Shouldn't there be a const and non-const, like there is for, say, CStringArray?
No because the operator does nto return a reference to a character in the string, it returns a copy of the character in the string.  that means that if you try

SomeString[2] = 'a';

however, it won't work.  The [] operator can be used to "examine" characters in the string, but can't be used to change them.  If it could, that is if it returned a reference to a character from the string rather than a copy, then yes, you would need a const and non-const version of operator [].
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 22

Expert Comment

by:nietod
ID: 1320428
The only explanation I can think of--and certainly can't confirm-- is that since the CString does't have another overload for operator [] , that there is a a global (non-class) operator [] overload somewhere.  And that what the compiler 's other option is, is to convert the CString to the type used by the global operator [].  That's assuming that [] isn't required to be part of a class.  I didn't look that up.
0
 
LVL 8

Expert Comment

by:trestan
ID: 1320429
Have you tried to use the casts? Actually a "long" type index also cause such problems. I use the "int" or "const" casting to solve the problem. As of the reasons, I guess that the overload [] in CStringArray may have some influence to its usage on CString. For the radical reason, I think you have to ask MS.
0
 
LVL 32

Expert Comment

by:jhance
ID: 1320430
nietod,

Why do you insist that CString doesn't have an overloaded operator []?  If you look in Afx.h you will see the following in class CString:

      TCHAR GetAt(int nIndex) const;      // 0 based
      TCHAR operator[](int nIndex) const; // same as GetAt

This looks like an overloaded [] operator to me.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1320431
That is a single overload. Where is the ambiguity?  The error suggests that it can't decide between two overloaded functions, what is the second one?
0
 

Author Comment

by:TylerRick
ID: 1320432
>You've got some other problem elsewhere in your code.  The
>following code compiles OK.  Post your declaration of
>strPathName.

strPathName is a parameter in my function:
CString
FindFileName(CString strPathName)
{
      CString strFileName;

      for (unsigned short int i = strPathName.GetLength() - 1; i >= 0; i--)
      {
            char charCurrent = strPathName[i];  
            if (charCurrent == '\\')
            {
                  break;
            }
      }
      
      strFileName = strPathName.Mid(i + 1);
      
      return strFileName;
}

jhance's example:
{
CString strPathName;
strPathName = "Testing";

for(int i=0; i<5; i++){
TCHAR charCurrent = strPathName[i];
}
Right, that works because i is signed. I don't want my i signed because it will never go < 0. I'm getting in trouble because I don't just use "int" like most people; I'm specifying "signed".

>That is a single overload. Where is the ambiguity?  The error
>suggests that it can't decide between two overloaded functions,
>what is the second one?
My point exactly!

>I tested and I have the same problem with an unsigned short
>index.  
Apparently, it won't work unless it has an int (signed instead of unsigned). I guess I'm stuck with the solution of casting:
char charCurrent = strPathName[(int)i];
Which works fine.

>No because the operator does nto return a reference to a
>character in the string, it returns a copy of the character in
>the string.  
I get it. I think it would be better if they let you use [] for changing part of the string as well.

It looks like no one has answer for why it can't implicitly cast to the required type, why it needs an explicit cast. Oh well, at least it compiles. That's what matters, I guess. Thanks all for the help!

Who wants the points? nietod?
0
 
LVL 32

Accepted Solution

by:
jhance earned 60 total points
ID: 1320433
>>It looks like no one has answer for why it can't implicitly cast to the required type

If you have a copy of Stroustruop's C++ Programming Language book, sections 6.2 (Operator Functions) and 6.3 (User-defined Type Conversion) give details (in fairly roudabout language) as to why your implicit conversion is not allowed.  I'm sure that there is an even more obtuse explanation in the C++ LRM if you're interested.


0
 
LVL 7

Expert Comment

by:psdavis
ID: 1320434
We all want the points, but I think nietod wins on volume.

Phillip
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now