我不明白这为什么行不通。了解模板和可变表达式折叠的人可以解释一下发生了什么,并给出一个可行的解决方案吗?
#include <iostream>
#include <string>
template <typename... Args>
void print(Args... args)
{
std::string sep = " ";
std::string end = "\n";
(std::cout << ... << sep << args) << end;
}
int main()
{
print(1, 2, 3);
}
它应该打印出每个参数,中间有一个空格,末尾有一个换行符。如果您删除了sep <<
,但在打印时每个参数之间没有空格,那么它就会起作用。
发布于 2017-05-01 21:31:48
二进制fold-expressions的语法必须是以下语法之一:
(pack op ... op init)
(init op ... op pack)
您所拥有的是(std::cout << ... << sep << args)
,它不适合这两种形式。你需要像(cout << ... << pack)
这样的东西,这就是为什么删除sep
是有效的。
相反,您可以将逗号折叠起来:
((std::cout << sep << args), ...);
或者使用递归:
template <class A, class... Args>
void print(A arg, Args... args) {
std::cout << arg;
if constexpr (sizeof...(Args) > 0) {
std::cout << sep;
print(args...);
}
}
发布于 2017-05-02 02:03:34
你真正想做的是:
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
使用了一个文本,以确保我使用右值)。
ostreamer
捕获对它是<<
'd的东西的引用,然后当它被<<
到ostream
时转储它们。
整个过程对编译器来说应该是透明的,所以一个好的优化器应该把涉及到的一切都去掉。
发布于 2018-10-11 06:43:59
另一种方法是下一种:
#include <iostream>
template<class U, class... T>
void printSpaced(const U& u, const T&... args)
{
using std::cout;
using std::endl;
((cout << u) << ... << (cout << ' ', args)) << endl;
}
这样你就不会得到前导/尾随空格
用法:
printSpaced(1, 2, "Hello", 4.5f); //Output 1 2 Hello 4.5 and no trailing space
https://stackoverflow.com/questions/43719789
复制相似问题