【问题标题】:Ambiguity when writing TStringList to TStream将 TStringList 写入 TStream 时的歧义
【发布时间】:2015-09-24 18:32:49
【问题描述】:

我正在开发一个使用流在客户端之间发送数据的项目。它实现了一堆流操作符来支持这一点。它在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 '>>(System::Classes::TStream 之间的歧义 &,bool &) 在 Common\Streams.h:28' 和 '>>(System::Classes::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 中运行良好。

【问题讨论】:

    标签: c++ c++builder tstringlist tstream c++builder-10-seattle


    【解决方案1】:

    您没有专门为TStringList* 定义的&gt;&gt; 运算符,因此编译器必须寻找匹配的候选对象以将TStringList* 指针转换为。任何指针都可以隐式转换为bool,并且编译器似乎认为编译器创建的临时bool 变量是可行的重载候选者,因此由于TStringList* 可以转换为TStrings* 和@ 987654328@(通过临时)。

    TStrings* 运算符更改为采用TStrings&amp; 参数(无论如何您都应该这样做,不要将对象指针传递给流式运算符),然后在调用运算符时将m_pIPAddressFilter 更改为*m_pIPAddressFilter。这样就不会有歧义了。

    *pStream >>
        ...
        *m_pIPAddressFilter
        ...;
    

    另外,您的 TStrings 运算符似乎不一致。 &lt;&lt; 正在使用中间 WideString 流出 UnicodeString 值(为什么?为什么要使用 static_cast?)。您的 &gt;&gt; 运算符正在使用中间 AnsiString 流式传输 UnicodeString 值。这些是不同的数据转换,因此当存在非 ASCII 字符时,您可能会损坏数据。您需要为两个运算符使用一致的字符串类型。您应该使用String 变量按原样流式传输TStrings 值,然后实现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;
    }
    

    【讨论】:

    • 好吧,我不是代码的原作者。它大约有一百万行代码,我负责将它从旧的 2010 版本中提升出来。我仍然觉得奇怪的是它在 C++ Builder 2010 中编译得很好。实际上,我确实尝试在此处发布之前为TStringList 添加特定版本,但它给出了完全相同的错误。关于 WideStrings 等,我认为这是将 Unicode 引入 RTL 时早期更新的一部分。我会给它一个额外的外观。我会尝试引用(尽管对代码进行了很多更改),但我相信编译器即使针对指针也会对其进行排序
    • 您没有说您是使用 32 位“经典”编译器、新的 32 位 clang 编译器还是 64 位编译器进行编译。我怀疑经典编译器和 clang 编译器在这方面的行为不同。
    • 它使用的是旧的经典 BCC32 编译器。我希望有一天能够有时间升级它,以便能够利用不错的新 C++ 功能,但第一步是让它在它曾经被装箱的旧式 BCC32 编译器上运行.... ohhh我说“老”了吗?我的意思是“经典”:P
    猜你喜欢
    • 2014-10-06
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2021-05-15
    相关资源
    最近更新 更多