如何为 boost::tuple 编写 `<<` 运算符?
在下面的示例代码中,它表明可以从第一个模板参数隐式创建 boost::tuple 。
因此,我无法编写 <<
运算符,因为它变得不明确。
我也不明白为什么 ostringstream& << float 也是不明确的。这没有任何隐含的构造。为什么这也会给出不明确的错误?
#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <sstream>
#include <string>
using namespace std;
class Myclass
{
};
typedef boost::tuple<int,float,Myclass> Mytuple;
ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)
{
float f = tuple_.get<1>();
//os_ << (int)tuple_.get<0>(); // Error because int is implicitly converted into Mytuple. WHYY?
//os_ << tuple_.get<1>(); // No Clue Why this is ambiguous.
//os_ << tuple_.get<2>(); // Error because no matching operator. Fine.
return os_;
}
int main()
{
Mytuple t1;
t1 = 3; // Working because int is implicitly converted into Mytuple!! WHY?
//t1 = 3.0f; // Error because no matching constructor. Fine.
return 0;
}
错误信息:
tupleTest2.C:18: 错误:ISO C++ 说这些是不明确的,甚至 尽管第一个最差的转换比最差的要好 第二个转换:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题不在于元组,而在于您的运算符。这工作正常:
问题是 ostringstream 从 ostream 继承了
operator<<
,它具有以下签名:ostringstream&允许使用运算符<<(ostringstream& os_, Mytuple tuple_)
。然后(将 T 更改为 c++ 中的所有可用类型,请参阅 operator<< ; 参考页
编辑
这是一个简化的示例(没有元组):
现在错误是:
上面的错误消息说:无法在两个运算符之间进行选择
operator<<(ostream&,...)
和operator<<(ostringstream&,...)。这也提出了另一个问题:你到底为什么需要
代码>运算符<<(ostringstream&,...)`?The problem is not with the tuple, but with your operator. This works fine :
The problem is that the ostringstream inherit
operator<<
from ostream, which has this signature :ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)
is allowed. Then the(change T with all available types in c++, see operator<< reference page
EDIT
Here is a simplified example (without a tuple) :
and the error is now :
The above error message says : it is not possible to choose between two operators
operator<<(ostream&,...)
andoperator<<(ostringstream&,...). This also raises another question : why on earth do you need
operator<<(ostringstream&,...)`?当您编写时,
没有与这两个参数匹配的函数。相反,编译器可以选择对任一参数应用隐式转换
,或者
后者将发生在 boost::tuple 构造函数中,该构造函数可以接受任意数量的参数,最多可达元组元素的数量。 (对于
float
会失败,因为float
可转换为int
。)重载流运算符时,使用基类作为左侧(
ostream
甚至basic_ostream
。编辑: 您可以通过投射 first 来消除调用的歧义然而
,使用 ostringstream 重载运算符仍然是一个坏主意,因为它无法与运算符链接一起
使用:
1) ostringstream&运算符<<(ostringstream&os_, Mytuple tuple_)
2) ostream& ostream::operator<<(char)
3)
ostream&运算符<<(ostream&&, boost::tuple
When you write
there is no function that matches both parameters. Instead the compiler has a choice to apply an implicit conversion on either parameter
or
The latter would happen with the
boost::tuple
constructor that can take any number of arguments up to number of tuple elements. (And withfloat
it fails, becausefloat
is convertible toint
.)When overloading stream operators, use the base class as the left hand side (
ostream
or evenbasic_ostream<CharT, Traits>
.Edit: You could disambiguate the call by casting the first argument.
However, overloading the operator with
ostringstream
is still a bad idea, because it won't work with operator chaining.will invoke:
1)
ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)
2)
ostream& ostream::operator<<(char)
3)
ostream& operator<<(ostream&&, boost::tuple<int,float,Myclass>
所有告诉您使用
::std::ostream
作为类型而不是::std::ostringstream
的人都是绝对正确的。您不应该以这种方式使用::std::ostringstream
。但我对你的代码的主要不满是令人痛苦地缺乏通用性。它仅适用于一种特定的元组类型,而不适用于所有类型。
因此,我用 C++0x 为
::std::tuple
编写了一个operator <<
,它适用于任何可以使用单独编写成员的元组。运算符<<
。它可能可以相对容易地转换为与 Boost 的元组类型一起使用。如下所示:这会将元组打印为
"(element1, element2, ...elementx)"
。All those people telling you to use
::std::ostream
for the type instead of::std::ostringstream
are absolutely correct. You shouldn't be using::std::ostringstream
that way.But my main beef with your code is the distressing lack of generality. It only works for one particular tuple type, and not all of them.
So I wrote an
operator <<
for::std::tuple
in C++0x that works for any tuple who's members can be individually written usingoperator <<
. It can probably be translated relatively easily to work with Boost's tuple type. Here it is:This prints out the tuple as
"(element1, element2, ...elementx)"
.