I'm working on a project that sends data between clients using streams. It implements a bunch of stream operators to support this. It worked fine in C++ Builder 2010 but now that I'm moving the project to C++ Builder 10 Seattle I get a weird error.
In one function a TStream is created and data written to it
*pStream >>
Version >>
m_iPortNumber >>
m_iHeartBeatTimeout >>
m_iMaxToRead >>
m_pIPAddressFilter >>
m_iRetries;
m_pIPAddressFilter here is a TStringList and the error is related to that. It reads
[bcc32 Error] E2015 Ambiguity between '>>(System::Classes::TStream &,bool &) at Common\Streams.h:28' and '>>(System::Classes::TStream &,System::Classes::TStrings *) at Common\Streams.h:42'
The implemented stream operators it's referring to look like this
PACKAGE TStream & operator <<(TStream &Stream, bool b)
{
Stream.WriteBuffer(&b, sizeof(b));
return Stream;
}
PACKAGE TStream & operator >>(TStream &Stream, bool &b)
{
Stream.ReadBuffer(&b, sizeof(b));
return Stream;
}
PACKAGE TStream & operator <<(TStream &Stream, TStrings *pList)
{
int Count;
int i;
Stream << (Count=pList->Count);
for (i=0; i<Count; i++)
Stream << static_cast<WideString> (pList->Strings[i]);
return Stream;
}
PACKAGE TStream & operator >>(TStream &Stream, TStrings *pList)
{
AnsiString s;
int Count;
pList->Clear();
Stream >> Count;
while (Count--)
{
Stream >> s;
pList->Add(s);
}
return Stream;
}
How can the compiler be confused by this and feel that it's ambiguous if the version taking a bool or the version taking TStrings should be used. TStrings is even a parent class of TStringList that is what is being written to the stream. As said, this worked fine in C++ Builder 2010.
You don't have an
>>operator defined specifically forTStringList*, so the compiler has to look for matching candidates to convert aTStringList*pointer to. Any pointer is implicitly convertible to abool, and it would seem that the compiler considers a compiler-created temporaryboolvariable is a viable overload candidate, thus an ambiguity sinceTStringList*is convertible to bothTStrings*andbool&(via a temp).Change your
TStrings*operators to takeTStrings¶meter instead (which you should do anyway, don't pass object pointers to streaming operators), and then changem_pIPAddressFilterto*m_pIPAddressFilterwhen invoking the operators. Then there will not be any ambiguity.On a separate note, your
TStringsoperators seem to be inconsistent.<<is streaming outUnicodeStringvalues using an intermediateWideString(Why? And why are you usingstatic_cast?). Your>>operator is streaming inUnicodeStringvalues using an intermediateAnsiStringinstead. Those are different data conversions, so you are likely to corrupt data when non-ASCII characters are present. You need to use consistent string types for both operators. You should be streaming theTStringsvalues as-is usingStringvariables, and then implementStringoperators to handle the actual streaming using a consistent format, like UTF-8, eg: