c++ conditional uni-directional iteratorNo known conversionsWhat are the differences between a pointer variable and a reference variable in C++?How do I iterate over the words of a string?How can I profile C++ code running on Linux?The Definitive C++ Book Guide and ListWhat is the effect of extern “C” in C++?What is the “-->” operator in C++?Why do we need virtual functions in C++?Easiest way to convert int to string in C++C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Why is reading lines from stdin much slower in C++ than Python?

Under what law can the U.S. arrest International Criminal Court (ICC) judges over war crimes probe?

How bitcoin nodes update UTXO set when their latests blocks are replaced?

Is it ok to put a subplot to a story that is never meant to contribute to the development of the main plot?

I think I may have violated academic integrity last year - what should I do?

How to prevent bad sectors?

Would the Geas spell work in a dead magic zone once you enter it?

Were pen cap holes designed to prevent death by suffocation if swallowed?

Can a wire having a 610-670 THz (frequency of blue light) AC frequency supply, generate blue light?

Tabulated absorption spectra of greenhouse gases?

I unknowingly submitted plagiarised work

Command to Search for Filenames Exceeding 143 Characters?

Is the first derivative operation on a signal a causal system?

Why doesn't the Earth's acceleration towards the Moon accumulate to push the Earth off its orbit?

Integrating an absolute function using Mathematica

Is one obligated to listen to a Rav?

Is there a general effective method to solve Smullyan style Knights and Knaves problems? Is the truth table method the most appropriate one?

How were these pictures of spacecraft wind tunnel testing taken?

Is there a down side to setting the sampling time of a SAR ADC as long as possible?

Mother abusing my finances

Do you play the upbeat when beginning to play a series of notes, and then after?

Graph with same number of edges and vertices is a loop?

What is the object moving across the ceiling in this stock footage?

Why does the 'metric Lagrangian' approach appear to fail in Newtonian mechanics?

Is this story about US tax office reasonable?



c++ conditional uni-directional iterator


No known conversionsWhat are the differences between a pointer variable and a reference variable in C++?How do I iterate over the words of a string?How can I profile C++ code running on Linux?The Definitive C++ Book Guide and ListWhat is the effect of extern “C” in C++?What is the “-->” operator in C++?Why do we need virtual functions in C++?Easiest way to convert int to string in C++C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Why is reading lines from stdin much slower in C++ than Python?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








24















I want to achieve something like the pseudo-code below:



string foo; // or vector<int> foo;
auto itr = bar? foo.begin() : foo.rbegin();
auto end = bar? foo.end() : foo.rend();
for ( ; itr != end; ++itr)
// SomeAction ...



That is, I want to set itr to be either a forward iterator or the reverse iterator, depending on some condition bar, to scan in forward or reverse direction.



Apparently code like that won't work, since forward iterator and reverse iterator has different type.



Note that I don't want to split into two loops, as those code like // SomeAction will be duplicated.



How can I do that?
Answers using C++11 and/or before are preferred.



Also, please elaborate if string and vector have different solutions.










share|improve this question

















  • 1





    May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

    – Scheff
    May 14 at 15:09












  • Does some action use/store the iterator apart from dereferencing?

    – Quimby
    May 14 at 15:12











  • Is bar a compile-time constant?

    – YSC
    May 14 at 15:12











  • @Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

    – AndyG
    May 14 at 19:23

















24















I want to achieve something like the pseudo-code below:



string foo; // or vector<int> foo;
auto itr = bar? foo.begin() : foo.rbegin();
auto end = bar? foo.end() : foo.rend();
for ( ; itr != end; ++itr)
// SomeAction ...



That is, I want to set itr to be either a forward iterator or the reverse iterator, depending on some condition bar, to scan in forward or reverse direction.



Apparently code like that won't work, since forward iterator and reverse iterator has different type.



Note that I don't want to split into two loops, as those code like // SomeAction will be duplicated.



How can I do that?
Answers using C++11 and/or before are preferred.



Also, please elaborate if string and vector have different solutions.










share|improve this question

















  • 1





    May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

    – Scheff
    May 14 at 15:09












  • Does some action use/store the iterator apart from dereferencing?

    – Quimby
    May 14 at 15:12











  • Is bar a compile-time constant?

    – YSC
    May 14 at 15:12











  • @Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

    – AndyG
    May 14 at 19:23













24












24








24








I want to achieve something like the pseudo-code below:



string foo; // or vector<int> foo;
auto itr = bar? foo.begin() : foo.rbegin();
auto end = bar? foo.end() : foo.rend();
for ( ; itr != end; ++itr)
// SomeAction ...



That is, I want to set itr to be either a forward iterator or the reverse iterator, depending on some condition bar, to scan in forward or reverse direction.



Apparently code like that won't work, since forward iterator and reverse iterator has different type.



Note that I don't want to split into two loops, as those code like // SomeAction will be duplicated.



How can I do that?
Answers using C++11 and/or before are preferred.



Also, please elaborate if string and vector have different solutions.










share|improve this question














I want to achieve something like the pseudo-code below:



string foo; // or vector<int> foo;
auto itr = bar? foo.begin() : foo.rbegin();
auto end = bar? foo.end() : foo.rend();
for ( ; itr != end; ++itr)
// SomeAction ...



That is, I want to set itr to be either a forward iterator or the reverse iterator, depending on some condition bar, to scan in forward or reverse direction.



Apparently code like that won't work, since forward iterator and reverse iterator has different type.



Note that I don't want to split into two loops, as those code like // SomeAction will be duplicated.



How can I do that?
Answers using C++11 and/or before are preferred.



Also, please elaborate if string and vector have different solutions.







c++ c++11






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked May 14 at 15:07









Robin HsuRobin Hsu

2,1141921




2,1141921







  • 1





    May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

    – Scheff
    May 14 at 15:09












  • Does some action use/store the iterator apart from dereferencing?

    – Quimby
    May 14 at 15:12











  • Is bar a compile-time constant?

    – YSC
    May 14 at 15:12











  • @Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

    – AndyG
    May 14 at 19:23












  • 1





    May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

    – Scheff
    May 14 at 15:09












  • Does some action use/store the iterator apart from dereferencing?

    – Quimby
    May 14 at 15:12











  • Is bar a compile-time constant?

    – YSC
    May 14 at 15:12











  • @Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

    – AndyG
    May 14 at 19:23







1




1





May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

– Scheff
May 14 at 15:09






May be, write a wrapper which contains both iterators (forward and reverse) and a flag which remembers which one is currently used. Additionally, you have to overload at least operator++() and operator!=().

– Scheff
May 14 at 15:09














Does some action use/store the iterator apart from dereferencing?

– Quimby
May 14 at 15:12





Does some action use/store the iterator apart from dereferencing?

– Quimby
May 14 at 15:12













Is bar a compile-time constant?

– YSC
May 14 at 15:12





Is bar a compile-time constant?

– YSC
May 14 at 15:12













@Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

– AndyG
May 14 at 19:23





@Scheff: Definitely possible, but lots of boilerplate. Even in C++20 (and that's an incomplete impl)

– AndyG
May 14 at 19:23












5 Answers
5






active

oldest

votes


















27














I would put the logic in a two-iterator function:



<template typename Iter>
void do_stuff(Iter first, Iter last)

for(; first != last; ++first)

// Do logic



bar ? do_stuff(foo.begin(), foo.end()) : do_stuff(foo.rbegin(), foo.rend());





share|improve this answer


















  • 7





    This function should probably be std::for_each().

    – moooeeeep
    May 15 at 9:28












  • In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

    – Mark B
    May 15 at 17:00


















16














The forward and reverse iterators are different types for most if not all containers, so unfortunately if it is a runtime decision, they can not simply be assigned to the same variable through the use of auto.



One option is to move the use of them into a template function:



template<class Iterator> void loop(Iterator begin, Iterator end)

for (auto itr = begin; itr != end; ++itr) ...


if (bar) loop(foo.begin(), foo.end());
else loop(foo.rbegin(), foo.rend());


In newer versions of C++ (C++14 and newer, so not C++11) the loop function can be a lambda, by using auto as the parameter type.



auto loop = [](auto begin, auto end)

for (auto itr = begin; itr != end; ++itr) ...
;


Another option, although somewhat more involved would be to make a wrapper type that can contain either an iterator or reverse iterator, and acts like an iterator itself with at least the comparison, increment and dereference operators.






share|improve this answer
































    9















    I don't want to split into two loops, as those code like // SomeAction will be duplicated.




    Put the action into a lambda.



    auto lambda = [&](char &val) // `ElementType &`

    // ...
    ;

    if (bar)

    for (auto &val : foo)
    lambda(val);

    else

    for (auto it = foo.rbegin(); it != foo.rend(); it++)
    lambda(*it);




    Alternatively, use indices rather than iterators. This will only work with containers that allow random access.



    std::size_t i, end, step;
    if (bar)

    i = 0;
    end = foo.size();
    step = 1;

    else

    i = foo.size() - 1;
    end = -1;
    step = -1;


    for (; i != end; i += step)

    // ...








    share|improve this answer

























    • Unfortunately, not a C++11 feature as the question was specifically tagged :(

      – Fire Lancer
      May 14 at 15:17






    • 1





      @FireLancer Forgot it was a C++14 thing, fixed.

      – HolyBlackCat
      May 14 at 15:23


















    9














    One option is to to write a function template for the loop that works with any iterator. Then conditionally call one instance of the template or another. The other answers already show examples of how to do that.



    By the way, the loop template might already exist in <algorithm> header depending on what you're doing. You could possibly use (but are not limited to) either std::for_each, std::accumulate or std::remove for example:



    auto body = [captures,needed,by,some,action](char c) 
    // SomeAction ...
    ;
    if (bar)
    std::for_each(foo.begin(), foo.end(), body);
    else
    std::for_each(foo.rbegin(), foo.rend(), body);


    If the body of the loop is reusable beyond this context, then you could use a named function as well, but only if you don't need captures. With captures, you can use a named functor type, but that involves quite a bit boilerplate.




    Another option is to use a type erasing iterator adaptor. It comes with a small runtime cost, and is probably not necessary here. But it is useful to mention in case people have a closely related problem where it is a better fit.



    Essentially, such adaptor is to templated iterator what std::function is to a templated functor argument. It removes the need for templates, which can be useful for abstract interfaces in particular. Unfortunately though, the standard library doesn't provide such iterator adaptor.



    An alterantive for an iterator adaptor is a range adaptor (also not in standard library):



    using t_erase = boost::adaptors::type_erased<>;
    auto range = bar
    ? boost::make_iterator_range(foo.begin(), foo.end()) | t_erase()
    : boost::make_iterator_range(foo.rbegin(), foo.rend()) | t_erase();
    for(char c : range)
    // SomeAction ...






    share|improve this answer
































      2














      Use an iterator class that abstracts this funtionality.



      An iterator has 3 basic functions:



      • Increment

      • Dereference

      • Check for equality

      We can use these as guidelines in creating an interface which abstracts this behavior. This interface is a bit cumbersome to use on it's own, but we can use it to build a wrapper class, GenericIterator, that can automatically be assigned any other iterator type.




      GenericIterator: A ready-made general purpose solution



      It's possible to write a GenericIterator class that can be assigned iterators from pretty much any collection, including the reverse iterators.



      int main() 
      bool iterate_forward;
      std::cin >> iterate_forward;

      std::vector<int> values 1, 2, 3 ;

      GenericIterator<int&> begin, end;

      if(iterate_forward)
      begin = values.begin();
      end = values.end();
      else
      begin = values.rbegin();
      end = values.rend();


      // Print out the values
      for(; begin != end; ++begin)
      std::cout << *begin << " ";




      You can download the entirety of the code from this github repo, which I'll be updating and improving as needed.



      Remarks on performance GenericIterator



      In terms of functionality, GenericIterator gives you everything you could possibly ask for. It's light-weight; and it's convenient; and it's easy to re-purpose if your code needs to read from a std::list or something other than a vector.



      However, due to the fundamental limitations of runtime polymorphism, it's significantly more difficult for the compiler to inline the virtual method calls. This means that GenericIterator carries more runtime overhead than other solutions.



      It's a good idea to favor static polymorphism and templates over runtime polymorphism when possible. If you're able to do so, use something like Mark B's solution, which will ultimately be more performant.



      Appendix



      Iterator interface definition. This class is used to implement GenericIterator. A GenericIterator contains a pointer to IteratorBase, which is used to achieve the runtime polymorphism. Thanks to the clone() method, GenericIterator remains both copyable and movable as expected.



      template <class Value>
      class IteratorBase

      public:
      virtual Value operator*() const = 0;
      virtual IteratorBase& operator++() = 0;
      virtual bool operator!=(IteratorBase const&) const = 0;
      virtual bool operator==(IteratorBase const&) const = 0;

      // We need this function for making copies of the iterator
      virtual IteratorBase* clone() const = 0;
      virtual ~IteratorBase() = default;
      ;


      Concrete class implementing IteratorBase. This class implements the behavior defined in IteratorBase. The iterator it contains is the actual iterator returned by the collection you're iterating over. In your case, it'd be either std::vector::iterator or std::vector::reverse_iterator.



      template <class Iter, class Value>
      class IteratorDerived : public IteratorBase<Value>

      Iter it;

      public:
      IteratorDerived() = default;
      IteratorDerived(Iter it) : it(it)
      IteratorDerived(IteratorDerived const&) = default;
      IteratorDerived(IteratorDerived&&) = default;

      Value operator*() const override return *it;
      IteratorBase<Value>& operator++() override

      ++it;
      return *this;


      bool operator!=(IteratorBase<Value> const& other) const override

      bool operator==(IteratorBase<Value> const& other) const override

      auto* derived = dynamic_cast<IteratorDerived const*>(&other);
      return derived != nullptr && it == derived->it;

      IteratorBase<Value>* clone() const override

      return new IteratorDerived(*this);

      ;


      GenericIterator implementation. This is the actual implementation of GenericIterator, based on IteratorBase and IteratorDerived. Any iterator given to GenericIterator is wrapped in the corresponding IteratorDerived, which is then assigned to the IteratorBase pointer.



      template <class Value>
      class GenericIterator

      std::unique_ptr<IteratorBase<Value>> iterator;

      public:
      using value_type = typename std::remove_reference<Value>::type;
      using reference = Value;

      GenericIterator() = default;
      GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())


      GenericIterator(GenericIterator&&) = default;

      // Creates a GenericIterator from an IteratorBase
      explicit GenericIterator(IteratorBase<Value> const& it)
      : iterator(it.clone())



      // Creates a GenericIterator from an IteratorDerived
      template <class Iter>
      explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
      : iterator(it.clone())



      // Creates a GenericIterator by wrapping another Iter
      template <class Iter>
      GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))



      GenericIterator& operator=(GenericIterator const& it)

      iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
      return *this;

      GenericIterator& operator=(GenericIterator&&) = default;

      Value operator*() const return *(*iterator);
      GenericIterator& operator++()

      ++(*iterator);
      return *this;

      void operator++(int)
      ++(*iterator);


      bool operator==(GenericIterator const& other) const

      return *iterator == *other.iterator;

      bool operator!=(GenericIterator const& other) const

      return *iterator != *other.iterator;

      ;





      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',
        autoActivateHeartbeat: false,
        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%2f56133546%2fc-conditional-uni-directional-iterator%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown

























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        27














        I would put the logic in a two-iterator function:



        <template typename Iter>
        void do_stuff(Iter first, Iter last)

        for(; first != last; ++first)

        // Do logic



        bar ? do_stuff(foo.begin(), foo.end()) : do_stuff(foo.rbegin(), foo.rend());





        share|improve this answer


















        • 7





          This function should probably be std::for_each().

          – moooeeeep
          May 15 at 9:28












        • In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

          – Mark B
          May 15 at 17:00















        27














        I would put the logic in a two-iterator function:



        <template typename Iter>
        void do_stuff(Iter first, Iter last)

        for(; first != last; ++first)

        // Do logic



        bar ? do_stuff(foo.begin(), foo.end()) : do_stuff(foo.rbegin(), foo.rend());





        share|improve this answer


















        • 7





          This function should probably be std::for_each().

          – moooeeeep
          May 15 at 9:28












        • In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

          – Mark B
          May 15 at 17:00













        27












        27








        27







        I would put the logic in a two-iterator function:



        <template typename Iter>
        void do_stuff(Iter first, Iter last)

        for(; first != last; ++first)

        // Do logic



        bar ? do_stuff(foo.begin(), foo.end()) : do_stuff(foo.rbegin(), foo.rend());





        share|improve this answer













        I would put the logic in a two-iterator function:



        <template typename Iter>
        void do_stuff(Iter first, Iter last)

        for(; first != last; ++first)

        // Do logic



        bar ? do_stuff(foo.begin(), foo.end()) : do_stuff(foo.rbegin(), foo.rend());






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered May 14 at 15:14









        Mark BMark B

        86.7k688168




        86.7k688168







        • 7





          This function should probably be std::for_each().

          – moooeeeep
          May 15 at 9:28












        • In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

          – Mark B
          May 15 at 17:00












        • 7





          This function should probably be std::for_each().

          – moooeeeep
          May 15 at 9:28












        • In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

          – Mark B
          May 15 at 17:00







        7




        7





        This function should probably be std::for_each().

        – moooeeeep
        May 15 at 9:28






        This function should probably be std::for_each().

        – moooeeeep
        May 15 at 9:28














        In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

        – Mark B
        May 15 at 17:00





        In simple cases that would definitely be better; I was (for no particular reason) assuming the logic was potentially more complicated where writing out the loop might make it clearer.

        – Mark B
        May 15 at 17:00













        16














        The forward and reverse iterators are different types for most if not all containers, so unfortunately if it is a runtime decision, they can not simply be assigned to the same variable through the use of auto.



        One option is to move the use of them into a template function:



        template<class Iterator> void loop(Iterator begin, Iterator end)

        for (auto itr = begin; itr != end; ++itr) ...


        if (bar) loop(foo.begin(), foo.end());
        else loop(foo.rbegin(), foo.rend());


        In newer versions of C++ (C++14 and newer, so not C++11) the loop function can be a lambda, by using auto as the parameter type.



        auto loop = [](auto begin, auto end)

        for (auto itr = begin; itr != end; ++itr) ...
        ;


        Another option, although somewhat more involved would be to make a wrapper type that can contain either an iterator or reverse iterator, and acts like an iterator itself with at least the comparison, increment and dereference operators.






        share|improve this answer





























          16














          The forward and reverse iterators are different types for most if not all containers, so unfortunately if it is a runtime decision, they can not simply be assigned to the same variable through the use of auto.



          One option is to move the use of them into a template function:



          template<class Iterator> void loop(Iterator begin, Iterator end)

          for (auto itr = begin; itr != end; ++itr) ...


          if (bar) loop(foo.begin(), foo.end());
          else loop(foo.rbegin(), foo.rend());


          In newer versions of C++ (C++14 and newer, so not C++11) the loop function can be a lambda, by using auto as the parameter type.



          auto loop = [](auto begin, auto end)

          for (auto itr = begin; itr != end; ++itr) ...
          ;


          Another option, although somewhat more involved would be to make a wrapper type that can contain either an iterator or reverse iterator, and acts like an iterator itself with at least the comparison, increment and dereference operators.






          share|improve this answer



























            16












            16








            16







            The forward and reverse iterators are different types for most if not all containers, so unfortunately if it is a runtime decision, they can not simply be assigned to the same variable through the use of auto.



            One option is to move the use of them into a template function:



            template<class Iterator> void loop(Iterator begin, Iterator end)

            for (auto itr = begin; itr != end; ++itr) ...


            if (bar) loop(foo.begin(), foo.end());
            else loop(foo.rbegin(), foo.rend());


            In newer versions of C++ (C++14 and newer, so not C++11) the loop function can be a lambda, by using auto as the parameter type.



            auto loop = [](auto begin, auto end)

            for (auto itr = begin; itr != end; ++itr) ...
            ;


            Another option, although somewhat more involved would be to make a wrapper type that can contain either an iterator or reverse iterator, and acts like an iterator itself with at least the comparison, increment and dereference operators.






            share|improve this answer















            The forward and reverse iterators are different types for most if not all containers, so unfortunately if it is a runtime decision, they can not simply be assigned to the same variable through the use of auto.



            One option is to move the use of them into a template function:



            template<class Iterator> void loop(Iterator begin, Iterator end)

            for (auto itr = begin; itr != end; ++itr) ...


            if (bar) loop(foo.begin(), foo.end());
            else loop(foo.rbegin(), foo.rend());


            In newer versions of C++ (C++14 and newer, so not C++11) the loop function can be a lambda, by using auto as the parameter type.



            auto loop = [](auto begin, auto end)

            for (auto itr = begin; itr != end; ++itr) ...
            ;


            Another option, although somewhat more involved would be to make a wrapper type that can contain either an iterator or reverse iterator, and acts like an iterator itself with at least the comparison, increment and dereference operators.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 14 at 15:22

























            answered May 14 at 15:14









            Fire LancerFire Lancer

            17k2592156




            17k2592156





















                9















                I don't want to split into two loops, as those code like // SomeAction will be duplicated.




                Put the action into a lambda.



                auto lambda = [&](char &val) // `ElementType &`

                // ...
                ;

                if (bar)

                for (auto &val : foo)
                lambda(val);

                else

                for (auto it = foo.rbegin(); it != foo.rend(); it++)
                lambda(*it);




                Alternatively, use indices rather than iterators. This will only work with containers that allow random access.



                std::size_t i, end, step;
                if (bar)

                i = 0;
                end = foo.size();
                step = 1;

                else

                i = foo.size() - 1;
                end = -1;
                step = -1;


                for (; i != end; i += step)

                // ...








                share|improve this answer

























                • Unfortunately, not a C++11 feature as the question was specifically tagged :(

                  – Fire Lancer
                  May 14 at 15:17






                • 1





                  @FireLancer Forgot it was a C++14 thing, fixed.

                  – HolyBlackCat
                  May 14 at 15:23















                9















                I don't want to split into two loops, as those code like // SomeAction will be duplicated.




                Put the action into a lambda.



                auto lambda = [&](char &val) // `ElementType &`

                // ...
                ;

                if (bar)

                for (auto &val : foo)
                lambda(val);

                else

                for (auto it = foo.rbegin(); it != foo.rend(); it++)
                lambda(*it);




                Alternatively, use indices rather than iterators. This will only work with containers that allow random access.



                std::size_t i, end, step;
                if (bar)

                i = 0;
                end = foo.size();
                step = 1;

                else

                i = foo.size() - 1;
                end = -1;
                step = -1;


                for (; i != end; i += step)

                // ...








                share|improve this answer

























                • Unfortunately, not a C++11 feature as the question was specifically tagged :(

                  – Fire Lancer
                  May 14 at 15:17






                • 1





                  @FireLancer Forgot it was a C++14 thing, fixed.

                  – HolyBlackCat
                  May 14 at 15:23













                9












                9








                9








                I don't want to split into two loops, as those code like // SomeAction will be duplicated.




                Put the action into a lambda.



                auto lambda = [&](char &val) // `ElementType &`

                // ...
                ;

                if (bar)

                for (auto &val : foo)
                lambda(val);

                else

                for (auto it = foo.rbegin(); it != foo.rend(); it++)
                lambda(*it);




                Alternatively, use indices rather than iterators. This will only work with containers that allow random access.



                std::size_t i, end, step;
                if (bar)

                i = 0;
                end = foo.size();
                step = 1;

                else

                i = foo.size() - 1;
                end = -1;
                step = -1;


                for (; i != end; i += step)

                // ...








                share|improve this answer
















                I don't want to split into two loops, as those code like // SomeAction will be duplicated.




                Put the action into a lambda.



                auto lambda = [&](char &val) // `ElementType &`

                // ...
                ;

                if (bar)

                for (auto &val : foo)
                lambda(val);

                else

                for (auto it = foo.rbegin(); it != foo.rend(); it++)
                lambda(*it);




                Alternatively, use indices rather than iterators. This will only work with containers that allow random access.



                std::size_t i, end, step;
                if (bar)

                i = 0;
                end = foo.size();
                step = 1;

                else

                i = foo.size() - 1;
                end = -1;
                step = -1;


                for (; i != end; i += step)

                // ...









                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited May 14 at 15:23

























                answered May 14 at 15:15









                HolyBlackCatHolyBlackCat

                18k33669




                18k33669












                • Unfortunately, not a C++11 feature as the question was specifically tagged :(

                  – Fire Lancer
                  May 14 at 15:17






                • 1





                  @FireLancer Forgot it was a C++14 thing, fixed.

                  – HolyBlackCat
                  May 14 at 15:23

















                • Unfortunately, not a C++11 feature as the question was specifically tagged :(

                  – Fire Lancer
                  May 14 at 15:17






                • 1





                  @FireLancer Forgot it was a C++14 thing, fixed.

                  – HolyBlackCat
                  May 14 at 15:23
















                Unfortunately, not a C++11 feature as the question was specifically tagged :(

                – Fire Lancer
                May 14 at 15:17





                Unfortunately, not a C++11 feature as the question was specifically tagged :(

                – Fire Lancer
                May 14 at 15:17




                1




                1





                @FireLancer Forgot it was a C++14 thing, fixed.

                – HolyBlackCat
                May 14 at 15:23





                @FireLancer Forgot it was a C++14 thing, fixed.

                – HolyBlackCat
                May 14 at 15:23











                9














                One option is to to write a function template for the loop that works with any iterator. Then conditionally call one instance of the template or another. The other answers already show examples of how to do that.



                By the way, the loop template might already exist in <algorithm> header depending on what you're doing. You could possibly use (but are not limited to) either std::for_each, std::accumulate or std::remove for example:



                auto body = [captures,needed,by,some,action](char c) 
                // SomeAction ...
                ;
                if (bar)
                std::for_each(foo.begin(), foo.end(), body);
                else
                std::for_each(foo.rbegin(), foo.rend(), body);


                If the body of the loop is reusable beyond this context, then you could use a named function as well, but only if you don't need captures. With captures, you can use a named functor type, but that involves quite a bit boilerplate.




                Another option is to use a type erasing iterator adaptor. It comes with a small runtime cost, and is probably not necessary here. But it is useful to mention in case people have a closely related problem where it is a better fit.



                Essentially, such adaptor is to templated iterator what std::function is to a templated functor argument. It removes the need for templates, which can be useful for abstract interfaces in particular. Unfortunately though, the standard library doesn't provide such iterator adaptor.



                An alterantive for an iterator adaptor is a range adaptor (also not in standard library):



                using t_erase = boost::adaptors::type_erased<>;
                auto range = bar
                ? boost::make_iterator_range(foo.begin(), foo.end()) | t_erase()
                : boost::make_iterator_range(foo.rbegin(), foo.rend()) | t_erase();
                for(char c : range)
                // SomeAction ...






                share|improve this answer





























                  9














                  One option is to to write a function template for the loop that works with any iterator. Then conditionally call one instance of the template or another. The other answers already show examples of how to do that.



                  By the way, the loop template might already exist in <algorithm> header depending on what you're doing. You could possibly use (but are not limited to) either std::for_each, std::accumulate or std::remove for example:



                  auto body = [captures,needed,by,some,action](char c) 
                  // SomeAction ...
                  ;
                  if (bar)
                  std::for_each(foo.begin(), foo.end(), body);
                  else
                  std::for_each(foo.rbegin(), foo.rend(), body);


                  If the body of the loop is reusable beyond this context, then you could use a named function as well, but only if you don't need captures. With captures, you can use a named functor type, but that involves quite a bit boilerplate.




                  Another option is to use a type erasing iterator adaptor. It comes with a small runtime cost, and is probably not necessary here. But it is useful to mention in case people have a closely related problem where it is a better fit.



                  Essentially, such adaptor is to templated iterator what std::function is to a templated functor argument. It removes the need for templates, which can be useful for abstract interfaces in particular. Unfortunately though, the standard library doesn't provide such iterator adaptor.



                  An alterantive for an iterator adaptor is a range adaptor (also not in standard library):



                  using t_erase = boost::adaptors::type_erased<>;
                  auto range = bar
                  ? boost::make_iterator_range(foo.begin(), foo.end()) | t_erase()
                  : boost::make_iterator_range(foo.rbegin(), foo.rend()) | t_erase();
                  for(char c : range)
                  // SomeAction ...






                  share|improve this answer



























                    9












                    9








                    9







                    One option is to to write a function template for the loop that works with any iterator. Then conditionally call one instance of the template or another. The other answers already show examples of how to do that.



                    By the way, the loop template might already exist in <algorithm> header depending on what you're doing. You could possibly use (but are not limited to) either std::for_each, std::accumulate or std::remove for example:



                    auto body = [captures,needed,by,some,action](char c) 
                    // SomeAction ...
                    ;
                    if (bar)
                    std::for_each(foo.begin(), foo.end(), body);
                    else
                    std::for_each(foo.rbegin(), foo.rend(), body);


                    If the body of the loop is reusable beyond this context, then you could use a named function as well, but only if you don't need captures. With captures, you can use a named functor type, but that involves quite a bit boilerplate.




                    Another option is to use a type erasing iterator adaptor. It comes with a small runtime cost, and is probably not necessary here. But it is useful to mention in case people have a closely related problem where it is a better fit.



                    Essentially, such adaptor is to templated iterator what std::function is to a templated functor argument. It removes the need for templates, which can be useful for abstract interfaces in particular. Unfortunately though, the standard library doesn't provide such iterator adaptor.



                    An alterantive for an iterator adaptor is a range adaptor (also not in standard library):



                    using t_erase = boost::adaptors::type_erased<>;
                    auto range = bar
                    ? boost::make_iterator_range(foo.begin(), foo.end()) | t_erase()
                    : boost::make_iterator_range(foo.rbegin(), foo.rend()) | t_erase();
                    for(char c : range)
                    // SomeAction ...






                    share|improve this answer















                    One option is to to write a function template for the loop that works with any iterator. Then conditionally call one instance of the template or another. The other answers already show examples of how to do that.



                    By the way, the loop template might already exist in <algorithm> header depending on what you're doing. You could possibly use (but are not limited to) either std::for_each, std::accumulate or std::remove for example:



                    auto body = [captures,needed,by,some,action](char c) 
                    // SomeAction ...
                    ;
                    if (bar)
                    std::for_each(foo.begin(), foo.end(), body);
                    else
                    std::for_each(foo.rbegin(), foo.rend(), body);


                    If the body of the loop is reusable beyond this context, then you could use a named function as well, but only if you don't need captures. With captures, you can use a named functor type, but that involves quite a bit boilerplate.




                    Another option is to use a type erasing iterator adaptor. It comes with a small runtime cost, and is probably not necessary here. But it is useful to mention in case people have a closely related problem where it is a better fit.



                    Essentially, such adaptor is to templated iterator what std::function is to a templated functor argument. It removes the need for templates, which can be useful for abstract interfaces in particular. Unfortunately though, the standard library doesn't provide such iterator adaptor.



                    An alterantive for an iterator adaptor is a range adaptor (also not in standard library):



                    using t_erase = boost::adaptors::type_erased<>;
                    auto range = bar
                    ? boost::make_iterator_range(foo.begin(), foo.end()) | t_erase()
                    : boost::make_iterator_range(foo.rbegin(), foo.rend()) | t_erase();
                    for(char c : range)
                    // SomeAction ...







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 15 at 10:14

























                    answered May 14 at 15:33









                    eerorikaeerorika

                    93.1k670139




                    93.1k670139





















                        2














                        Use an iterator class that abstracts this funtionality.



                        An iterator has 3 basic functions:



                        • Increment

                        • Dereference

                        • Check for equality

                        We can use these as guidelines in creating an interface which abstracts this behavior. This interface is a bit cumbersome to use on it's own, but we can use it to build a wrapper class, GenericIterator, that can automatically be assigned any other iterator type.




                        GenericIterator: A ready-made general purpose solution



                        It's possible to write a GenericIterator class that can be assigned iterators from pretty much any collection, including the reverse iterators.



                        int main() 
                        bool iterate_forward;
                        std::cin >> iterate_forward;

                        std::vector<int> values 1, 2, 3 ;

                        GenericIterator<int&> begin, end;

                        if(iterate_forward)
                        begin = values.begin();
                        end = values.end();
                        else
                        begin = values.rbegin();
                        end = values.rend();


                        // Print out the values
                        for(; begin != end; ++begin)
                        std::cout << *begin << " ";




                        You can download the entirety of the code from this github repo, which I'll be updating and improving as needed.



                        Remarks on performance GenericIterator



                        In terms of functionality, GenericIterator gives you everything you could possibly ask for. It's light-weight; and it's convenient; and it's easy to re-purpose if your code needs to read from a std::list or something other than a vector.



                        However, due to the fundamental limitations of runtime polymorphism, it's significantly more difficult for the compiler to inline the virtual method calls. This means that GenericIterator carries more runtime overhead than other solutions.



                        It's a good idea to favor static polymorphism and templates over runtime polymorphism when possible. If you're able to do so, use something like Mark B's solution, which will ultimately be more performant.



                        Appendix



                        Iterator interface definition. This class is used to implement GenericIterator. A GenericIterator contains a pointer to IteratorBase, which is used to achieve the runtime polymorphism. Thanks to the clone() method, GenericIterator remains both copyable and movable as expected.



                        template <class Value>
                        class IteratorBase

                        public:
                        virtual Value operator*() const = 0;
                        virtual IteratorBase& operator++() = 0;
                        virtual bool operator!=(IteratorBase const&) const = 0;
                        virtual bool operator==(IteratorBase const&) const = 0;

                        // We need this function for making copies of the iterator
                        virtual IteratorBase* clone() const = 0;
                        virtual ~IteratorBase() = default;
                        ;


                        Concrete class implementing IteratorBase. This class implements the behavior defined in IteratorBase. The iterator it contains is the actual iterator returned by the collection you're iterating over. In your case, it'd be either std::vector::iterator or std::vector::reverse_iterator.



                        template <class Iter, class Value>
                        class IteratorDerived : public IteratorBase<Value>

                        Iter it;

                        public:
                        IteratorDerived() = default;
                        IteratorDerived(Iter it) : it(it)
                        IteratorDerived(IteratorDerived const&) = default;
                        IteratorDerived(IteratorDerived&&) = default;

                        Value operator*() const override return *it;
                        IteratorBase<Value>& operator++() override

                        ++it;
                        return *this;


                        bool operator!=(IteratorBase<Value> const& other) const override

                        bool operator==(IteratorBase<Value> const& other) const override

                        auto* derived = dynamic_cast<IteratorDerived const*>(&other);
                        return derived != nullptr && it == derived->it;

                        IteratorBase<Value>* clone() const override

                        return new IteratorDerived(*this);

                        ;


                        GenericIterator implementation. This is the actual implementation of GenericIterator, based on IteratorBase and IteratorDerived. Any iterator given to GenericIterator is wrapped in the corresponding IteratorDerived, which is then assigned to the IteratorBase pointer.



                        template <class Value>
                        class GenericIterator

                        std::unique_ptr<IteratorBase<Value>> iterator;

                        public:
                        using value_type = typename std::remove_reference<Value>::type;
                        using reference = Value;

                        GenericIterator() = default;
                        GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())


                        GenericIterator(GenericIterator&&) = default;

                        // Creates a GenericIterator from an IteratorBase
                        explicit GenericIterator(IteratorBase<Value> const& it)
                        : iterator(it.clone())



                        // Creates a GenericIterator from an IteratorDerived
                        template <class Iter>
                        explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
                        : iterator(it.clone())



                        // Creates a GenericIterator by wrapping another Iter
                        template <class Iter>
                        GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))



                        GenericIterator& operator=(GenericIterator const& it)

                        iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
                        return *this;

                        GenericIterator& operator=(GenericIterator&&) = default;

                        Value operator*() const return *(*iterator);
                        GenericIterator& operator++()

                        ++(*iterator);
                        return *this;

                        void operator++(int)
                        ++(*iterator);


                        bool operator==(GenericIterator const& other) const

                        return *iterator == *other.iterator;

                        bool operator!=(GenericIterator const& other) const

                        return *iterator != *other.iterator;

                        ;





                        share|improve this answer





























                          2














                          Use an iterator class that abstracts this funtionality.



                          An iterator has 3 basic functions:



                          • Increment

                          • Dereference

                          • Check for equality

                          We can use these as guidelines in creating an interface which abstracts this behavior. This interface is a bit cumbersome to use on it's own, but we can use it to build a wrapper class, GenericIterator, that can automatically be assigned any other iterator type.




                          GenericIterator: A ready-made general purpose solution



                          It's possible to write a GenericIterator class that can be assigned iterators from pretty much any collection, including the reverse iterators.



                          int main() 
                          bool iterate_forward;
                          std::cin >> iterate_forward;

                          std::vector<int> values 1, 2, 3 ;

                          GenericIterator<int&> begin, end;

                          if(iterate_forward)
                          begin = values.begin();
                          end = values.end();
                          else
                          begin = values.rbegin();
                          end = values.rend();


                          // Print out the values
                          for(; begin != end; ++begin)
                          std::cout << *begin << " ";




                          You can download the entirety of the code from this github repo, which I'll be updating and improving as needed.



                          Remarks on performance GenericIterator



                          In terms of functionality, GenericIterator gives you everything you could possibly ask for. It's light-weight; and it's convenient; and it's easy to re-purpose if your code needs to read from a std::list or something other than a vector.



                          However, due to the fundamental limitations of runtime polymorphism, it's significantly more difficult for the compiler to inline the virtual method calls. This means that GenericIterator carries more runtime overhead than other solutions.



                          It's a good idea to favor static polymorphism and templates over runtime polymorphism when possible. If you're able to do so, use something like Mark B's solution, which will ultimately be more performant.



                          Appendix



                          Iterator interface definition. This class is used to implement GenericIterator. A GenericIterator contains a pointer to IteratorBase, which is used to achieve the runtime polymorphism. Thanks to the clone() method, GenericIterator remains both copyable and movable as expected.



                          template <class Value>
                          class IteratorBase

                          public:
                          virtual Value operator*() const = 0;
                          virtual IteratorBase& operator++() = 0;
                          virtual bool operator!=(IteratorBase const&) const = 0;
                          virtual bool operator==(IteratorBase const&) const = 0;

                          // We need this function for making copies of the iterator
                          virtual IteratorBase* clone() const = 0;
                          virtual ~IteratorBase() = default;
                          ;


                          Concrete class implementing IteratorBase. This class implements the behavior defined in IteratorBase. The iterator it contains is the actual iterator returned by the collection you're iterating over. In your case, it'd be either std::vector::iterator or std::vector::reverse_iterator.



                          template <class Iter, class Value>
                          class IteratorDerived : public IteratorBase<Value>

                          Iter it;

                          public:
                          IteratorDerived() = default;
                          IteratorDerived(Iter it) : it(it)
                          IteratorDerived(IteratorDerived const&) = default;
                          IteratorDerived(IteratorDerived&&) = default;

                          Value operator*() const override return *it;
                          IteratorBase<Value>& operator++() override

                          ++it;
                          return *this;


                          bool operator!=(IteratorBase<Value> const& other) const override

                          bool operator==(IteratorBase<Value> const& other) const override

                          auto* derived = dynamic_cast<IteratorDerived const*>(&other);
                          return derived != nullptr && it == derived->it;

                          IteratorBase<Value>* clone() const override

                          return new IteratorDerived(*this);

                          ;


                          GenericIterator implementation. This is the actual implementation of GenericIterator, based on IteratorBase and IteratorDerived. Any iterator given to GenericIterator is wrapped in the corresponding IteratorDerived, which is then assigned to the IteratorBase pointer.



                          template <class Value>
                          class GenericIterator

                          std::unique_ptr<IteratorBase<Value>> iterator;

                          public:
                          using value_type = typename std::remove_reference<Value>::type;
                          using reference = Value;

                          GenericIterator() = default;
                          GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())


                          GenericIterator(GenericIterator&&) = default;

                          // Creates a GenericIterator from an IteratorBase
                          explicit GenericIterator(IteratorBase<Value> const& it)
                          : iterator(it.clone())



                          // Creates a GenericIterator from an IteratorDerived
                          template <class Iter>
                          explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
                          : iterator(it.clone())



                          // Creates a GenericIterator by wrapping another Iter
                          template <class Iter>
                          GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))



                          GenericIterator& operator=(GenericIterator const& it)

                          iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
                          return *this;

                          GenericIterator& operator=(GenericIterator&&) = default;

                          Value operator*() const return *(*iterator);
                          GenericIterator& operator++()

                          ++(*iterator);
                          return *this;

                          void operator++(int)
                          ++(*iterator);


                          bool operator==(GenericIterator const& other) const

                          return *iterator == *other.iterator;

                          bool operator!=(GenericIterator const& other) const

                          return *iterator != *other.iterator;

                          ;





                          share|improve this answer



























                            2












                            2








                            2







                            Use an iterator class that abstracts this funtionality.



                            An iterator has 3 basic functions:



                            • Increment

                            • Dereference

                            • Check for equality

                            We can use these as guidelines in creating an interface which abstracts this behavior. This interface is a bit cumbersome to use on it's own, but we can use it to build a wrapper class, GenericIterator, that can automatically be assigned any other iterator type.




                            GenericIterator: A ready-made general purpose solution



                            It's possible to write a GenericIterator class that can be assigned iterators from pretty much any collection, including the reverse iterators.



                            int main() 
                            bool iterate_forward;
                            std::cin >> iterate_forward;

                            std::vector<int> values 1, 2, 3 ;

                            GenericIterator<int&> begin, end;

                            if(iterate_forward)
                            begin = values.begin();
                            end = values.end();
                            else
                            begin = values.rbegin();
                            end = values.rend();


                            // Print out the values
                            for(; begin != end; ++begin)
                            std::cout << *begin << " ";




                            You can download the entirety of the code from this github repo, which I'll be updating and improving as needed.



                            Remarks on performance GenericIterator



                            In terms of functionality, GenericIterator gives you everything you could possibly ask for. It's light-weight; and it's convenient; and it's easy to re-purpose if your code needs to read from a std::list or something other than a vector.



                            However, due to the fundamental limitations of runtime polymorphism, it's significantly more difficult for the compiler to inline the virtual method calls. This means that GenericIterator carries more runtime overhead than other solutions.



                            It's a good idea to favor static polymorphism and templates over runtime polymorphism when possible. If you're able to do so, use something like Mark B's solution, which will ultimately be more performant.



                            Appendix



                            Iterator interface definition. This class is used to implement GenericIterator. A GenericIterator contains a pointer to IteratorBase, which is used to achieve the runtime polymorphism. Thanks to the clone() method, GenericIterator remains both copyable and movable as expected.



                            template <class Value>
                            class IteratorBase

                            public:
                            virtual Value operator*() const = 0;
                            virtual IteratorBase& operator++() = 0;
                            virtual bool operator!=(IteratorBase const&) const = 0;
                            virtual bool operator==(IteratorBase const&) const = 0;

                            // We need this function for making copies of the iterator
                            virtual IteratorBase* clone() const = 0;
                            virtual ~IteratorBase() = default;
                            ;


                            Concrete class implementing IteratorBase. This class implements the behavior defined in IteratorBase. The iterator it contains is the actual iterator returned by the collection you're iterating over. In your case, it'd be either std::vector::iterator or std::vector::reverse_iterator.



                            template <class Iter, class Value>
                            class IteratorDerived : public IteratorBase<Value>

                            Iter it;

                            public:
                            IteratorDerived() = default;
                            IteratorDerived(Iter it) : it(it)
                            IteratorDerived(IteratorDerived const&) = default;
                            IteratorDerived(IteratorDerived&&) = default;

                            Value operator*() const override return *it;
                            IteratorBase<Value>& operator++() override

                            ++it;
                            return *this;


                            bool operator!=(IteratorBase<Value> const& other) const override

                            bool operator==(IteratorBase<Value> const& other) const override

                            auto* derived = dynamic_cast<IteratorDerived const*>(&other);
                            return derived != nullptr && it == derived->it;

                            IteratorBase<Value>* clone() const override

                            return new IteratorDerived(*this);

                            ;


                            GenericIterator implementation. This is the actual implementation of GenericIterator, based on IteratorBase and IteratorDerived. Any iterator given to GenericIterator is wrapped in the corresponding IteratorDerived, which is then assigned to the IteratorBase pointer.



                            template <class Value>
                            class GenericIterator

                            std::unique_ptr<IteratorBase<Value>> iterator;

                            public:
                            using value_type = typename std::remove_reference<Value>::type;
                            using reference = Value;

                            GenericIterator() = default;
                            GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())


                            GenericIterator(GenericIterator&&) = default;

                            // Creates a GenericIterator from an IteratorBase
                            explicit GenericIterator(IteratorBase<Value> const& it)
                            : iterator(it.clone())



                            // Creates a GenericIterator from an IteratorDerived
                            template <class Iter>
                            explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
                            : iterator(it.clone())



                            // Creates a GenericIterator by wrapping another Iter
                            template <class Iter>
                            GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))



                            GenericIterator& operator=(GenericIterator const& it)

                            iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
                            return *this;

                            GenericIterator& operator=(GenericIterator&&) = default;

                            Value operator*() const return *(*iterator);
                            GenericIterator& operator++()

                            ++(*iterator);
                            return *this;

                            void operator++(int)
                            ++(*iterator);


                            bool operator==(GenericIterator const& other) const

                            return *iterator == *other.iterator;

                            bool operator!=(GenericIterator const& other) const

                            return *iterator != *other.iterator;

                            ;





                            share|improve this answer















                            Use an iterator class that abstracts this funtionality.



                            An iterator has 3 basic functions:



                            • Increment

                            • Dereference

                            • Check for equality

                            We can use these as guidelines in creating an interface which abstracts this behavior. This interface is a bit cumbersome to use on it's own, but we can use it to build a wrapper class, GenericIterator, that can automatically be assigned any other iterator type.




                            GenericIterator: A ready-made general purpose solution



                            It's possible to write a GenericIterator class that can be assigned iterators from pretty much any collection, including the reverse iterators.



                            int main() 
                            bool iterate_forward;
                            std::cin >> iterate_forward;

                            std::vector<int> values 1, 2, 3 ;

                            GenericIterator<int&> begin, end;

                            if(iterate_forward)
                            begin = values.begin();
                            end = values.end();
                            else
                            begin = values.rbegin();
                            end = values.rend();


                            // Print out the values
                            for(; begin != end; ++begin)
                            std::cout << *begin << " ";




                            You can download the entirety of the code from this github repo, which I'll be updating and improving as needed.



                            Remarks on performance GenericIterator



                            In terms of functionality, GenericIterator gives you everything you could possibly ask for. It's light-weight; and it's convenient; and it's easy to re-purpose if your code needs to read from a std::list or something other than a vector.



                            However, due to the fundamental limitations of runtime polymorphism, it's significantly more difficult for the compiler to inline the virtual method calls. This means that GenericIterator carries more runtime overhead than other solutions.



                            It's a good idea to favor static polymorphism and templates over runtime polymorphism when possible. If you're able to do so, use something like Mark B's solution, which will ultimately be more performant.



                            Appendix



                            Iterator interface definition. This class is used to implement GenericIterator. A GenericIterator contains a pointer to IteratorBase, which is used to achieve the runtime polymorphism. Thanks to the clone() method, GenericIterator remains both copyable and movable as expected.



                            template <class Value>
                            class IteratorBase

                            public:
                            virtual Value operator*() const = 0;
                            virtual IteratorBase& operator++() = 0;
                            virtual bool operator!=(IteratorBase const&) const = 0;
                            virtual bool operator==(IteratorBase const&) const = 0;

                            // We need this function for making copies of the iterator
                            virtual IteratorBase* clone() const = 0;
                            virtual ~IteratorBase() = default;
                            ;


                            Concrete class implementing IteratorBase. This class implements the behavior defined in IteratorBase. The iterator it contains is the actual iterator returned by the collection you're iterating over. In your case, it'd be either std::vector::iterator or std::vector::reverse_iterator.



                            template <class Iter, class Value>
                            class IteratorDerived : public IteratorBase<Value>

                            Iter it;

                            public:
                            IteratorDerived() = default;
                            IteratorDerived(Iter it) : it(it)
                            IteratorDerived(IteratorDerived const&) = default;
                            IteratorDerived(IteratorDerived&&) = default;

                            Value operator*() const override return *it;
                            IteratorBase<Value>& operator++() override

                            ++it;
                            return *this;


                            bool operator!=(IteratorBase<Value> const& other) const override

                            bool operator==(IteratorBase<Value> const& other) const override

                            auto* derived = dynamic_cast<IteratorDerived const*>(&other);
                            return derived != nullptr && it == derived->it;

                            IteratorBase<Value>* clone() const override

                            return new IteratorDerived(*this);

                            ;


                            GenericIterator implementation. This is the actual implementation of GenericIterator, based on IteratorBase and IteratorDerived. Any iterator given to GenericIterator is wrapped in the corresponding IteratorDerived, which is then assigned to the IteratorBase pointer.



                            template <class Value>
                            class GenericIterator

                            std::unique_ptr<IteratorBase<Value>> iterator;

                            public:
                            using value_type = typename std::remove_reference<Value>::type;
                            using reference = Value;

                            GenericIterator() = default;
                            GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())


                            GenericIterator(GenericIterator&&) = default;

                            // Creates a GenericIterator from an IteratorBase
                            explicit GenericIterator(IteratorBase<Value> const& it)
                            : iterator(it.clone())



                            // Creates a GenericIterator from an IteratorDerived
                            template <class Iter>
                            explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
                            : iterator(it.clone())



                            // Creates a GenericIterator by wrapping another Iter
                            template <class Iter>
                            GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))



                            GenericIterator& operator=(GenericIterator const& it)

                            iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
                            return *this;

                            GenericIterator& operator=(GenericIterator&&) = default;

                            Value operator*() const return *(*iterator);
                            GenericIterator& operator++()

                            ++(*iterator);
                            return *this;

                            void operator++(int)
                            ++(*iterator);


                            bool operator==(GenericIterator const& other) const

                            return *iterator == *other.iterator;

                            bool operator!=(GenericIterator const& other) const

                            return *iterator != *other.iterator;

                            ;






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited May 14 at 21:52

























                            answered May 14 at 21:20









                            J. Antonio PerezJ. Antonio Perez

                            4,781926




                            4,781926



























                                draft saved

                                draft discarded
















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid


                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.

                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56133546%2fc-conditional-uni-directional-iterator%23new-answer', 'question_page');

                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

                                Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

                                What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company