C ++ 17折叠表达式的经典示例是打印所有参数:
template<typename ... Args>
void print(Args ... args)
{
(cout << ... << args);
}
示例:
print("Hello", 12, 234.3, complex<float>{12.3f, 32.8f});
输出:
Hello12234.3(12.3,32.8)
我想在输出中添加换行符。但是,我找不到一个很好的方法来做到这一点,到目前为止我发现的最好:
template<typename ... Args>
void print(Args ... args)
{
(cout << ... << ((std::ostringstream{} << args << "\n").str()));
}
然而,这不是零开销,因为它为每个参数构造了一个临时的ostringstream
。
以下版本不起作用:
(cout << ... << " " << args);
error: expression not permitted as operand of fold expression
和
(cout << ... << (" " << args));
error: invalid operands to binary expression
我理解为什么最后两个版本不起作用。 使用折叠表达式是否有更优雅的解决方案?
答案 0 :(得分:11)
更新:T.C.下面的评论提供了更好的解决方案:
template<typename ... Args>
void print(Args ... args)
{
((cout << args << '\n'), ...);
}
您可以在逗号运算符上使用 fold表达式:
template<typename ... Args>
void print(Args ... args)
{
([](const auto& x){ cout << x << "\n"; }(args), ...);
}
用法:
int main()
{
print("a", 1, 1000);
}
一
1
1000
(注意:这也会打印一个尾随换行符。)
说明:
[](const auto& x){ cout << x << "\n"; }
是一个lambda,其x
打印x
和'\n'
。
[](const auto& x){ cout << x << "\n"; }(args)
立即使用args
调用lambda。
([](const auto& x){ cout << x << "\n"; }(args), ...)
是逗号运算符的折叠表达式,它以下列方式展开:
// (pseudocode)
[](const auto& x){ cout << x << "\n"; }(args<0>),
[](const auto& x){ cout << x << "\n"; }(args<1>),
[](const auto& x){ cout << x << "\n"; }(args<2>),
// ...
[](const auto& x){ cout << x << "\n"; }(args<N>)
答案 1 :(得分:6)
order by
接受一个函数对象SELECT
notification.type,
notification.triggerer,
notification.to_what,
ANY_VALUE(user_data.name) AS name,
ANY_VALUE(user_data.surname) AS surname,
ANY_VALUE(user_data.avatarimage) AS avatarimage,
COUNT(*) AS counter
FROM notification
INNER JOIN user_data
ON notification.triggerer = user_data.owner
WHERE notification.owner = "c6cecc891f6c4cc84cc0b62062578e52"
AND isdelete=0
GROUP BY notification.triggerer, notification.type, notification.to_what
ORDER BY notification.id DESC
LIMIT 0,100
,并返回一个新的函数对象。返回值在每个args上运行f。它在每个args上“重复”repeat
。
f
使用:
f
这使用折叠表达式,但只是间接表达。老实说,你可以用C ++ 14编写这个(只是template<class F>
auto repeat( F&& f ) {
return [f=std::forward<F>(f)](auto&&...args)mutable{
( void(f(args)), ... );
};
}
的主体会更加丑陋)。
我们还可以编写一个与repeat
( [](auto&&x){ std::cout << x << "\n"; } )
( args... );
配合使用的流媒体“更内联”并直接使用折叠表达式:
repeat
然后我们像这样使用它:
<<
template<class F>
struct ostreamer_t {
F f;
friend std::ostream& operator<<( std::ostream& os, ostreamer_t&& self ) {
std::move(self).f(os);
return os;
}
};
template<class F>
ostreamer_t<F> ostreamer( F&& f ) { return {std::forward<F>(f)}; }
接受一个函数对象。它返回一个重载(std::cout << ... << ostreamer([&](auto&& os){ os << " " << args;}));
的对象,这样当你在左边传递一个ostream时,它会用ostream调用函数对象。
没有创建临时流。