“字符串流”论证顺序麻烦

发布于 2024-11-13 01:43:26 字数 804 浏览 6 评论 0原文

我在 stringstream 方面遇到了一个奇怪的问题。

#include "stdafx.h"
#include "iostream"
#include "sstream"

using namespace std;

struct Test
{
    float f;
};

wstringstream& operator <<( wstringstream& sstream , const Test& test )
{
    sstream << test.f;
    return sstream;
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test a;
    a.f = 1.2f;

    wstringstream ss;
    ss << L"text" << a << endl; // error C2679!
    ss << a << L"text" << endl; // it works well..

    getchar();
    return 0;
}

问题就在这里:

ss << L"text" << a << endl; // error C2679!
ss << a << L"text" << endl; // it works well..

这两个语句之间的唯一区别是参数顺序。为什么第一个语句失败而第二个语句有效?

I'm experiencing a weird problem with stringstream.

#include "stdafx.h"
#include "iostream"
#include "sstream"

using namespace std;

struct Test
{
    float f;
};

wstringstream& operator <<( wstringstream& sstream , const Test& test )
{
    sstream << test.f;
    return sstream;
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test a;
    a.f = 1.2f;

    wstringstream ss;
    ss << L"text" << a << endl; // error C2679!
    ss << a << L"text" << endl; // it works well..

    getchar();
    return 0;
}

The problem is here:

ss << L"text" << a << endl; // error C2679!
ss << a << L"text" << endl; // it works well..

The only difference between these two statements is argument order. Why does the first statement fail whereas the second one works?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤星 2024-11-20 01:43:26

不要将您的运算符<<限制为只能与wstringstream一起使用,编写它以便它可以与任何宽流一起使用:

std::wostream& operator <<(std::wostream& sstream, Test const& test)
{
    return sstream << test.f;
}

或与任何流(宽或窄)一起使用:

template<typename CharT, typename TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT, TraitsT>& sstream, Test const& test)
{
    return sstream << test.f;
}

Don't restrict your operator<< only to working with wstringstream, write it so it will work with any wide stream:

std::wostream& operator <<(std::wostream& sstream, Test const& test)
{
    return sstream << test.f;
}

or with any stream (wide or narrow):

template<typename CharT, typename TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT, TraitsT>& sstream, Test const& test)
{
    return sstream << test.f;
}
我为君王 2024-11-20 01:43:26

简短回答

问题是 ss << L"text" 为您提供一个 std::wostream,而不是 std::wstringstream

您仅为 std::wstringstream 创建了一个 operator<<,因此下一个操作(您尝试在 a 上执行的操作)失败了。

长答案

当您编写类似的内容时,

ss << L"text" << a << endl;

您不会调用具有四个参数的函数。

事实上,您正在链接多个操作:

((ss << L"text") << a) << endl;

这是有效的,因为每个 operator<< 操作都会返回对原始流对象的引用,以便您可以继续以这种方式链接更多操作。

但是,由于 iostream 形成继承层次结构,并且 operator<< 适用于任何输出流,因此对 wstringstream 操作的返回类型比 wstringstream 稍微不太具体。

事实上,ss << L"text" 计算结果为 wostream&wostreamwstringstream 的基类之一)。该引用仍然引用相同的原始流对象...但它具有基类类型。

因此,涉及 a 的第二个操作具有以下活动操作数:

  • a wostream& (在左侧)
  • a Test (在右侧)

< strong>但是你没有wostream&运算符<<(wostream&, Test const&)。您只创建了一个 wstringstream&运算符<<(wstringstream& sstream, Test const& test),因此没有匹配项。

因此,事实上,在为宽 iostream 创建 operator<< 时,您应该使其适用于所有 wostream(显然没有将其限制为 wstringstreams 的原因:

wostream& operator<<(wostream& sstream, Test const& test)
{
    sstream << test.f;
    return sstream;
}

更进一步,为什么要限制自己使用宽流?为什么不也有普通的呢?

template<typename CharT, typename TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& sstream, Test const& test)
{
    sstream << test.f;
    return sstream;
}

现在,您将能够正确地将 Test 类的对象流式传输到 wostreamostream 及其所有后代。

Short answer

The problem is that ss << L"text" gives you a std::wostream, not a std::wstringstream.

You only created an operator<< for std::wstringstream, so the next operation (which you're trying to do on a) fails.

Long answer

When you write something like

ss << L"text" << a << endl;

you are not invoking a function with four arguments.

You are, in fact, chaining multiple operations:

((ss << L"text") << a) << endl;

This works because each operator<< operation returns a reference to the original stream object, so that you can continue chaining further operations on in this manner.

But because iostreams form an inheritance hierarchy, and because operator<< is applicable to any output stream, the return type from your operation on wstringstream is something a little less specific than wstringstream.

In fact, ss << L"text" evaluates to a wostream& (wostream being one of wstringstream's base classes). The reference still refers to the same, original stream object... but it has a base class type.

So, your second operation involving a has the following active operands:

  • a wostream& (on the LHS)
  • a Test (on the RHS)

But you have no wostream& operator<<(wostream&, Test const&). You only created a wstringstream& operator<<(wstringstream& sstream, Test const& test), so there's no match.

So, in fact, when creating an operator<< for wide iostreams you should make it work for all wostreams (clearly there is no reason to limit it to wstringstreams):

wostream& operator<<(wostream& sstream, Test const& test)
{
    sstream << test.f;
    return sstream;
}

Going further, why limit yourself to wide streams? Why not normal ones too?

template<typename CharT, typename TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& sstream, Test const& test)
{
    sstream << test.f;
    return sstream;
}

Now you will be able to stream objects of your Test class into wostreams, ostreams, and all their descendants, properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文