• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1086
  • Last Modified:

CString::operator[] ambiguity.

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
TylerRick
Asked:
TylerRick
  • 5
  • 3
  • 2
  • +2
1 Solution
 
psdavisCommented:
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
 
nietodCommented:
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
 
trestanCommented:
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
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
TylerRickAuthor Commented:
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
 
jhanceCommented:
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
 
nietodCommented:
Does it work if you make your counter an unsigned short int?  That would be a good test.  
0
 
nietodCommented:
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
 
nietodCommented:
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
 
trestanCommented:
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
 
jhanceCommented:
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
 
nietodCommented:
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
 
TylerRickAuthor Commented:
>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
 
jhanceCommented:
>>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
 
psdavisCommented:
We all want the points, but I think nietod wins on volume.

Phillip
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 3
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now