是否可以在折叠表达式中插入额外的操作?
Is it possible to insert extra operation in fold expression?
在C++17中,折叠表达式可用,所以要打印参数,我们可以使用
#define EOL '\n'
template<typename ...Args>
void output_argus(Args&&... args)
{
(cout << ... << args) << EOL;
}
int main()
{
output_argus(1, "test", 5.6f);
}
有输出
1test5.6
如果我想使用折叠表达式向每个元素附加一个额外的字符 '\n'
以获得以下结果怎么办?
1
test
5.6
这可能吗?如果是,如何?
What if I would like using the fold expression appending an extra character '\n' to each element to get the following results?
您可以使用逗号运算符的强大功能
((std::cout << args << std::endl), ...);
或者,按照 Quentin 的建议(谢谢)和您的要求,您可以简单地使用 \n
而不是 std::endl
(以避免多次刷新流)
((std::cout << args << '\n'), ...);
我知道逗号运算符可能是最简单的方法,但为了完整起见,我想出了一些办法,主要是因为我想炫耀一下我对 iomanip 的概括。标准库 iomanips 是函数。有一个带有函数指针的 <<
重载。我将其扩展为通过引用获取和 return 流的任意可调用对象。
template <class Stream, class Func>
auto operator << (Stream& s, Func f) ->
std::enable_if_t<std::is_same_v<decltype(f(s)), Stream&>, Stream&>
{
return f(s);
}
有了我们工具箱中的这个小工具,就可以轻松编写折叠表达式来完成我们想要的任何事情。
template<typename ...Args>
void output_args(Args&&... args)
{
(std::cout << ... << [&](auto& x)->auto&{return x << args << '\n';});
}
此技术可用于我们需要捕获折叠表达式的值而不是其副作用的场景。逗号运算符在这种情况下用处不大。
这是@n.m.没有粗鲁的全局贪婪的解决方案operator<<
.
template<class Os>
struct chain_stream {
Os& stream;
template<class Rhs,
std::enable_if_t<std::is_same_v<Os&, decltype(std::declval<Os&>() << std::declval<Rhs>())>, bool> =true
>
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Rhs&& rhs ) {
os.stream << std::forward<Rhs>(rhs);
return os;
}
// iomanipulator:
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Os&(*rhs)(Os&) ) {
os.stream << rhs;
return os;
}
template<class Rhs,
std::enable_if_t<
std::is_same_v< std::result_of_t< Rhs&&(chain_stream const&) >, void >
|| std::is_same_v< std::result_of_t< Rhs&&(chain_stream const&) >, Os& >,
bool> =true
>
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Rhs&& rhs ) {
std::forward<Rhs>(rhs)( os );
return os;
}
};
现在我们可以做:
(chain_stream{std::cout} << ... << [&](auto& x){x << args << '\n';});
而且有效。
在C++17中,折叠表达式可用,所以要打印参数,我们可以使用
#define EOL '\n'
template<typename ...Args>
void output_argus(Args&&... args)
{
(cout << ... << args) << EOL;
}
int main()
{
output_argus(1, "test", 5.6f);
}
有输出
1test5.6
如果我想使用折叠表达式向每个元素附加一个额外的字符 '\n'
以获得以下结果怎么办?
1
test
5.6
这可能吗?如果是,如何?
What if I would like using the fold expression appending an extra character '\n' to each element to get the following results?
您可以使用逗号运算符的强大功能
((std::cout << args << std::endl), ...);
或者,按照 Quentin 的建议(谢谢)和您的要求,您可以简单地使用 \n
而不是 std::endl
(以避免多次刷新流)
((std::cout << args << '\n'), ...);
我知道逗号运算符可能是最简单的方法,但为了完整起见,我想出了一些办法,主要是因为我想炫耀一下我对 iomanip 的概括。标准库 iomanips 是函数。有一个带有函数指针的 <<
重载。我将其扩展为通过引用获取和 return 流的任意可调用对象。
template <class Stream, class Func>
auto operator << (Stream& s, Func f) ->
std::enable_if_t<std::is_same_v<decltype(f(s)), Stream&>, Stream&>
{
return f(s);
}
有了我们工具箱中的这个小工具,就可以轻松编写折叠表达式来完成我们想要的任何事情。
template<typename ...Args>
void output_args(Args&&... args)
{
(std::cout << ... << [&](auto& x)->auto&{return x << args << '\n';});
}
此技术可用于我们需要捕获折叠表达式的值而不是其副作用的场景。逗号运算符在这种情况下用处不大。
这是@n.m.没有粗鲁的全局贪婪的解决方案operator<<
.
template<class Os>
struct chain_stream {
Os& stream;
template<class Rhs,
std::enable_if_t<std::is_same_v<Os&, decltype(std::declval<Os&>() << std::declval<Rhs>())>, bool> =true
>
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Rhs&& rhs ) {
os.stream << std::forward<Rhs>(rhs);
return os;
}
// iomanipulator:
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Os&(*rhs)(Os&) ) {
os.stream << rhs;
return os;
}
template<class Rhs,
std::enable_if_t<
std::is_same_v< std::result_of_t< Rhs&&(chain_stream const&) >, void >
|| std::is_same_v< std::result_of_t< Rhs&&(chain_stream const&) >, Os& >,
bool> =true
>
friend chain_stream<Os> const& operator<<( chain_stream<Os> const& os, Rhs&& rhs ) {
std::forward<Rhs>(rhs)( os );
return os;
}
};
现在我们可以做:
(chain_stream{std::cout} << ... << [&](auto& x){x << args << '\n';});
而且有效。