Is it possible to insert extra operation in fold expression?
Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
In C++17, fold expression is available, so to print arguments, we could use
template<typename ...Args>
void output_argus(Args&&... args)
(cout << ... << args) << EOL;
int main()
output_argus(1, "test", 5.6f);
having the output1test5.6
What if I would like using the fold expression appending an extra character 'n'
to each element to get the following results?
1
test
5.6
Is that even possible? If yes, how?
c++ templates c++17 variadic-templates fold-expression
add a comment |Â
up vote
7
down vote
favorite
In C++17, fold expression is available, so to print arguments, we could use
template<typename ...Args>
void output_argus(Args&&... args)
(cout << ... << args) << EOL;
int main()
output_argus(1, "test", 5.6f);
having the output1test5.6
What if I would like using the fold expression appending an extra character 'n'
to each element to get the following results?
1
test
5.6
Is that even possible? If yes, how?
c++ templates c++17 variadic-templates fold-expression
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
In C++17, fold expression is available, so to print arguments, we could use
template<typename ...Args>
void output_argus(Args&&... args)
(cout << ... << args) << EOL;
int main()
output_argus(1, "test", 5.6f);
having the output1test5.6
What if I would like using the fold expression appending an extra character 'n'
to each element to get the following results?
1
test
5.6
Is that even possible? If yes, how?
c++ templates c++17 variadic-templates fold-expression
In C++17, fold expression is available, so to print arguments, we could use
template<typename ...Args>
void output_argus(Args&&... args)
(cout << ... << args) << EOL;
int main()
output_argus(1, "test", 5.6f);
having the output1test5.6
What if I would like using the fold expression appending an extra character 'n'
to each element to get the following results?
1
test
5.6
Is that even possible? If yes, how?
c++ templates c++17 variadic-templates fold-expression
c++ templates c++17 variadic-templates fold-expression
edited 5 hours ago
max66
31.7k63459
31.7k63459
asked 5 hours ago
r0ng
610723
610723
add a comment |Â
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
8
down vote
accepted
What if I would like using the fold expression appending an extra character 'n' to each element to get the following results?
You can use the power of the comma operator
((std::cout << args << std::endl), ...);
or, as suggested by Quentin (thanks) and as you asked, you can simply use n
instead of std::endl
(to avoid multiple flushing of the stream)
((std::cout << args << 'n'), ...);
2
std::endl
is completely overkill, OP just wants a newline.
â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
add a comment |Â
up vote
1
down vote
I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
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);
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
(std::cout << ... << [&](auto& x)->auto&return x << args << 'n';);
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.
A free greedy<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).
â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
add a comment |Â
up vote
1
down vote
This is @n.m.'s solution without the rude global greedy 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 >
;
now we can do:
(chain_streamstd::cout << ... << [&](auto& x)x << args << 'n';);
and it works.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
8
down vote
accepted
What if I would like using the fold expression appending an extra character 'n' to each element to get the following results?
You can use the power of the comma operator
((std::cout << args << std::endl), ...);
or, as suggested by Quentin (thanks) and as you asked, you can simply use n
instead of std::endl
(to avoid multiple flushing of the stream)
((std::cout << args << 'n'), ...);
2
std::endl
is completely overkill, OP just wants a newline.
â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
add a comment |Â
up vote
8
down vote
accepted
What if I would like using the fold expression appending an extra character 'n' to each element to get the following results?
You can use the power of the comma operator
((std::cout << args << std::endl), ...);
or, as suggested by Quentin (thanks) and as you asked, you can simply use n
instead of std::endl
(to avoid multiple flushing of the stream)
((std::cout << args << 'n'), ...);
2
std::endl
is completely overkill, OP just wants a newline.
â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
add a comment |Â
up vote
8
down vote
accepted
up vote
8
down vote
accepted
What if I would like using the fold expression appending an extra character 'n' to each element to get the following results?
You can use the power of the comma operator
((std::cout << args << std::endl), ...);
or, as suggested by Quentin (thanks) and as you asked, you can simply use n
instead of std::endl
(to avoid multiple flushing of the stream)
((std::cout << args << 'n'), ...);
What if I would like using the fold expression appending an extra character 'n' to each element to get the following results?
You can use the power of the comma operator
((std::cout << args << std::endl), ...);
or, as suggested by Quentin (thanks) and as you asked, you can simply use n
instead of std::endl
(to avoid multiple flushing of the stream)
((std::cout << args << 'n'), ...);
edited 5 hours ago
answered 5 hours ago
max66
31.7k63459
31.7k63459
2
std::endl
is completely overkill, OP just wants a newline.
â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
add a comment |Â
2
std::endl
is completely overkill, OP just wants a newline.
â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
2
2
std::endl
is completely overkill, OP just wants a newline.â Quentin
5 hours ago
std::endl
is completely overkill, OP just wants a newline.â Quentin
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
@Quentin - good point; added to the answer.
â max66
5 hours ago
add a comment |Â
up vote
1
down vote
I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
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);
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
(std::cout << ... << [&](auto& x)->auto&return x << args << 'n';);
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.
A free greedy<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).
â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
add a comment |Â
up vote
1
down vote
I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
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);
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
(std::cout << ... << [&](auto& x)->auto&return x << args << 'n';);
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.
A free greedy<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).
â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
add a comment |Â
up vote
1
down vote
up vote
1
down vote
I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
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);
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
(std::cout << ... << [&](auto& x)->auto&return x << args << 'n';);
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.
I know that the comma operator is probably the easiest way to do that, but for completeness here's something I came up with, mainly because I wanted to show off my little generalisation of iomanip. The standard library iomanips are functions. There's an <<
overload that takes a function pointer. I extended that for arbitrary callable objects that take and return streams by reference.
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);
With this little tool in our toolbox, it's easy to write a fold expression that does absolutely anything we want.
template<typename ...Args>
void output_args(Args&&... args)
(std::cout << ... << [&](auto& x)->auto&return x << args << 'n';);
This technique can be used in scenarios where we need to capture the value of the fold expression, rather than its side effects. The comma operator is less useful in such contexts.
answered 4 hours ago
n.m.
69.6k882165
69.6k882165
A free greedy<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).
â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
add a comment |Â
A free greedy<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).
â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
A free greedy
<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).â Yakk - Adam Nevraumont
3 hours ago
A free greedy
<<
operator seems rude. Instead, I'd tag one of the types (the function or the stream).â Yakk - Adam Nevraumont
3 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
See my solution based off yours.
â Yakk - Adam Nevraumont
2 hours ago
add a comment |Â
up vote
1
down vote
This is @n.m.'s solution without the rude global greedy 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 >
;
now we can do:
(chain_streamstd::cout << ... << [&](auto& x)x << args << 'n';);
and it works.
add a comment |Â
up vote
1
down vote
This is @n.m.'s solution without the rude global greedy 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 >
;
now we can do:
(chain_streamstd::cout << ... << [&](auto& x)x << args << 'n';);
and it works.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
This is @n.m.'s solution without the rude global greedy 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 >
;
now we can do:
(chain_streamstd::cout << ... << [&](auto& x)x << args << 'n';);
and it works.
This is @n.m.'s solution without the rude global greedy 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 >
;
now we can do:
(chain_streamstd::cout << ... << [&](auto& x)x << args << 'n';);
and it works.
answered 2 hours ago
Yakk - Adam Nevraumont
176k19179361
176k19179361
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53216992%2fis-it-possible-to-insert-extra-operation-in-fold-expression%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password