你真正想要做的是:
std::string sep = " ";
std::string end = "\n";
(std::cout << ... << (sep << args)) << end;
,因为你想(sep << args)
与std::cout
左折叠。这是行不通的,因为sep << args
不知道它正在流入std::cout
或者流式传输; <<
只在流媒体的左边是流。
总之,问题是sep << args
不明白它是流媒体。
您的其他问题是不够lambda。
我们可以解决这个问题。
template<class F>
struct ostreamer_t {
F f;
friend std::ostream& operator<<(std::ostream& os, ostreamer_t&& self) {
self.f(os);
return os;
}
template<class T>
friend auto operator<<(ostreamer_t self, T&& t) {
auto f = [g = std::move(self.f), &t](auto&& os)mutable {
std::move(g)(os);
os << t;
};
return ostreamer_t<decltype(f)>{std::move(f)};
}
};
struct do_nothing_t {
template<class...Args>
void operator()(Args&&...)const {}
};
const ostreamer_t<do_nothing_t> ostreamer{{}};
template <typename... Args>
void print(Args... args)
{
std::string sep = " ";
std::string end = "\n";
(std::cout << ... << (ostreamer << sep << args)) << end;
}
live example。 (我也用sep
的文字来确保我用rvalues工作)。
ostreamer
捕获对事物的引用,它是<<
'd,然后将它们转储到<<
到ostream
。
整个过程对于编译器来说应该是透明的,所以体面的优化器应该会消除所有涉及的事情。
对于'(std :: cout << sep << args,...);'它说“表达式不允许作为折叠表达式的操作数”。然而,它表明我把括号放在它的一部分上,比如'((std :: cout << sep << args),...);'但是这会跳过打印第一个参数。有没有这一行的版本可以工作? – nickeb96
@ nickeb96对,忘了括号。我不确定你对其余的意思,它不会跳过第一个论点。 – Barry
啊,我得到了第二部分的工作。它打印一个领先的'sep'然而。有没有一种简单的方法可以在每个参数之间使用'sep'?还是需要一个更复杂的解决方案,如递归? – nickeb96