我以为是operator<<
的电话将生成一个双参数函数调用。那么,为什么这不能编译呢?
#include <iostream> // ostream
#include <iomanip> // setw, setfill
using std::ostream; using std::setw; using std::setfill;
struct Clock {
int h_, m_, s_;
Clock(int hours, int minutes, int seconds)
: h_{hours}, m_{minutes}, s_{seconds} {}
void setClock(int hours, int minutes, int seconds) {
h_ = hours; m_ = minutes; s_ = seconds;
}
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_); // ERROR
}
};
错误是(gcc-6)
$ g++-6 -std=gnu++1y ...
file.cpp: In function ‘std::ostream& operator<<(std::ostream&, const Clock&)’:
file.cpp:745:33: error: no match for call to ‘(operator<<(std::ostream&, const Clock&)::<lambda(std::ostream&, int)>) (const int&)’
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
^
我也试过调用os << w2(os,c.h_)
但 gcc 和我一致认为这是无稽之谈。我还尽可能地尝试了 lambda:
auto w2 = [](auto&os, auto f) {
return os << setw(2) << setfill( '0' ) << f; };
也没有运气。
有什么提示吗?
最佳答案
I thought the call of the
operator<<
would generate a two-parameter function call.
不,调用重载 operator<<
与调用二元函数基本相同:
a << b;
// is equivalent to
operator<<(a, b);
// or to
a.operator<<(b);
您要做的是调用 operator<<
使用返回 ostream&
的 lambda作为右边的参数,但你没有传递 ostream&
lambda 本身的参数。
os << w2(os,c.h_)
在语法上是有效的,但不会编译,因为没有 operator<<(ostream&, ostream&)
定义。
您可以做的是简单地调用 lambda 而无需流式传输它:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
w2(os, c.h_);
os <<':';
w2(os, c.m_);
os << ':';
return w2(os, c.s_);
}
如果你想实现你想要的语法,你需要做更多的工作。这是一个可能的解决方案:
template <typename TF>
struct streamable : TF
{
streamable(TF&& f) : TF{std::move(f)} { }
};
template <typename TF>
auto& operator<<(ostream& os, const streamable<TF>& s)
{
s(os); return os;
}
template <typename TF>
auto make_streamable_impl(TF f)
{
return streamable<TF>(std::move(f));
}
template <typename TF>
auto make_streamable(TF f)
{
return [&](auto&& x) mutable
{
return make_streamable_impl([&](ostream& os) -> auto&
{
f(os, x);
return os;
});
};
}
用法:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = make_streamable([](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; });
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
}
请注意,真正的实现可能应该是 perfectly-capture the arguments进入 lambda。
关于c++ - 如何为 ostream 创建 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42456399/