Is it possible to insert extra operation in fold expression?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite
1












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 output
1test5.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?










share|improve this question



























    up vote
    7
    down vote

    favorite
    1












    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 output
    1test5.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?










    share|improve this question

























      up vote
      7
      down vote

      favorite
      1









      up vote
      7
      down vote

      favorite
      1






      1





      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 output
      1test5.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?










      share|improve this question















      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 output
      1test5.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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 5 hours ago









      max66

      31.7k63459




      31.7k63459










      asked 5 hours ago









      r0ng

      610723




      610723






















          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'), ...); 





          share|improve this answer


















          • 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

















          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.






          share|improve this answer




















          • 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

















          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.






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            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






























            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'), ...); 





            share|improve this answer


















            • 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














            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'), ...); 





            share|improve this answer


















            • 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












            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'), ...); 





            share|improve this answer















            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'), ...); 






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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












            • 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












            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.






            share|improve this answer




















            • 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














            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.






            share|improve this answer




















            • 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












            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.






            share|improve this answer












            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            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
















            • 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










            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.






            share|improve this answer
























              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.






              share|improve this answer






















                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.






                share|improve this answer












                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.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 2 hours ago









                Yakk - Adam Nevraumont

                176k19179361




                176k19179361



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    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













































































                    Popular posts from this blog

                    How to check contact read email or not when send email to Individual?

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?