Reputation: 12942
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
.
Upvotes: 0
Views: 310
Reputation: 598309
You don't have an >>
operator defined specifically for TStringList*
, so the compiler has to look for matching candidates to convert a TStringList*
pointer to. Any pointer is implicitly convertible to a bool
, and it would seem that the compiler considers a compiler-created temporary bool
variable is a viable overload candidate, thus an ambiguity since TStringList*
is convertible to both TStrings*
and bool&
(via a temp).
Change your TStrings*
operators to take TStrings&
parameter instead (which you should do anyway, don't pass object pointers to streaming operators), and then change m_pIPAddressFilter
to *m_pIPAddressFilter
when invoking the operators. Then there will not be any ambiguity.
*pStream >>
...
*m_pIPAddressFilter
...;
On a separate note, your TStrings
operators seem to be inconsistent. <<
is streaming out UnicodeString
values using an intermediate WideString
(Why? And why are you using static_cast
?). Your >>
operator is streaming in UnicodeString
values using an intermediate AnsiString
instead. 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 the TStrings
values as-is using String
variables, and then implement String
operators to handle the actual streaming using a consistent format, like UTF-8, eg:
PACKAGE TStream & operator <<(TStream &Stream, String s)
{
UTF8String utf = s;
int Count = utf.Length();
Stream << Count;
Stream.WriteBuffer(utf.c_str(), Count);
return Stream;
}
PACKAGE TStream & operator >>(TStream &Stream, String &s)
{
UTF8String utf;
int Count;
Stream >> Count;
s.SetLength(Count);
Stream.ReadBuffer(utf.c_str(), Count);
s = utf;
return Stream;
}
PACKAGE TStream & operator <<(TStream &Stream, TStrings &pList)
{
int Count = pList.Count;
Stream << Count;
for (int i = 0; i < Count; ++i)
Stream << pList.Strings[i];
return Stream;
}
PACKAGE TStream & operator >>(TStream &Stream, TStrings &pList)
{
pList.BeginUpdate();
try
{
pList.Clear();
String s;
int Count;
Stream >> Count;
while (Count--)
{
Stream >> s;
pList.Add(s);
}
}
__finally {
pList.EndUpdate();
}
return Stream;
}
Upvotes: 0