Я работаю над проектом, который передает данные между клиентами, используя потоки. Он реализует несколько потоковых операторов для поддержки этого. Это работало нормально в C++ Builder 2010
но теперь, когда я перемещаю проект в C++ Builder 10 Seattle
Я получаю странную ошибку.
В одной функции TStream
создается и данные записываются в него
*pStream >>
Version >>
m_iPortNumber >>
m_iHeartBeatTimeout >>
m_iMaxToRead >>
m_pIPAddressFilter >>
m_iRetries;
m_pIPAddressFilter
вот TStringList
и ошибка связана с этим. Это читает
[bcc32 Ошибка] E2015 Неоднозначность между ‘>> (Система :: Классы :: TStream
&, BOOL &) в Common \ Streams.h: 28 ‘и’ >> (Система :: Классы :: TStream
&, System :: Classes :: TStrings *) в Common \ Streams.h: 42 ‘
Реализованные потоковые операторы, это выглядит так
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;
}
Как может смущать компилятор и чувствовать, что это неоднозначно, если версия принимает bool
или версия, берущая TStrings
должен быть использован. TStrings
даже родительский класс TStringList
это то, что пишется в поток. Как сказано, это работало нормально в C++ Builder 2010
,
У вас нет >>
оператор, определенный специально для TStringList*
поэтому компилятор должен искать подходящих кандидатов для преобразования TStringList*
указатель на. Любой указатель неявно преобразуется в bool
и может показаться, что компилятор считает созданный компилятором временный bool
переменная является жизнеспособным кандидатом на перегрузку, поэтому TStringList*
конвертируется в оба TStrings*
а также bool&
(через временную шкалу).
Измени свой TStrings*
операторы взять TStrings&
параметр вместо этого (что вы должны сделать в любом случае, не передавайте указатели объекта на потоковые операторы), а затем измените m_pIPAddressFilter
в *m_pIPAddressFilter
при вызове операторов. Тогда не будет никакой двусмысленности.
*pStream >>
...
*m_pIPAddressFilter
...;
На отдельном примечании ваш TStrings
операторы кажутся непоследовательными. <<
течет из UnicodeString
значения с использованием промежуточного WideString
(Почему? И почему вы используете static_cast
?). Ваш >>
оператор транслируется в UnicodeString
значения с использованием промежуточного AnsiString
вместо. Это разные преобразования данных, поэтому вы можете повредить данные, если присутствуют символы, отличные от ASCII. Вы должны использовать согласованные строковые типы для обоих операторов. Вы должны транслировать TStrings
значения как-использует String
переменные, а затем реализовать String
операторы для обработки фактической потоковой передачи с использованием согласованного формата, такого как UTF-8, например:
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;
}
Других решений пока нет …