C++ range based loop with special case for first item?












12















I find myself often with code that looks like this:



bool isFirst = true;
for(const auto &item: items)
{
if(!isFirst)
{
// do something
}
// Normal processing
isFirst = false;
}


Seems like there ought to be better way to express this as it's a common pattern in functions that act like "join".










share|improve this question

























  • That's why I'm sad that bools don't have -- anymore...

    – Quentin
    11 hours ago











  • Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

    – dyukha
    11 hours ago








  • 2





    When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

    – WhozCraig
    11 hours ago






  • 4





    Possible duplicate of Skipping in Range-based for based on 'index'?

    – hlscalon
    11 hours ago






  • 1





    Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

    – bpeikes
    7 hours ago
















12















I find myself often with code that looks like this:



bool isFirst = true;
for(const auto &item: items)
{
if(!isFirst)
{
// do something
}
// Normal processing
isFirst = false;
}


Seems like there ought to be better way to express this as it's a common pattern in functions that act like "join".










share|improve this question

























  • That's why I'm sad that bools don't have -- anymore...

    – Quentin
    11 hours ago











  • Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

    – dyukha
    11 hours ago








  • 2





    When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

    – WhozCraig
    11 hours ago






  • 4





    Possible duplicate of Skipping in Range-based for based on 'index'?

    – hlscalon
    11 hours ago






  • 1





    Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

    – bpeikes
    7 hours ago














12












12








12


0






I find myself often with code that looks like this:



bool isFirst = true;
for(const auto &item: items)
{
if(!isFirst)
{
// do something
}
// Normal processing
isFirst = false;
}


Seems like there ought to be better way to express this as it's a common pattern in functions that act like "join".










share|improve this question
















I find myself often with code that looks like this:



bool isFirst = true;
for(const auto &item: items)
{
if(!isFirst)
{
// do something
}
// Normal processing
isFirst = false;
}


Seems like there ought to be better way to express this as it's a common pattern in functions that act like "join".







c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







bpeikes

















asked 11 hours ago









bpeikesbpeikes

59251744




59251744













  • That's why I'm sad that bools don't have -- anymore...

    – Quentin
    11 hours ago











  • Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

    – dyukha
    11 hours ago








  • 2





    When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

    – WhozCraig
    11 hours ago






  • 4





    Possible duplicate of Skipping in Range-based for based on 'index'?

    – hlscalon
    11 hours ago






  • 1





    Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

    – bpeikes
    7 hours ago



















  • That's why I'm sad that bools don't have -- anymore...

    – Quentin
    11 hours ago











  • Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

    – dyukha
    11 hours ago








  • 2





    When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

    – WhozCraig
    11 hours ago






  • 4





    Possible duplicate of Skipping in Range-based for based on 'index'?

    – hlscalon
    11 hours ago






  • 1





    Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

    – bpeikes
    7 hours ago

















That's why I'm sad that bools don't have -- anymore...

– Quentin
11 hours ago





That's why I'm sad that bools don't have -- anymore...

– Quentin
11 hours ago













Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

– dyukha
11 hours ago







Shouldn't it be else { /* Normal processing */ }? In this case you can look at this answer (it skips the last element, the idea is similar): stackoverflow.com/a/35372958/2956272

– dyukha
11 hours ago






2




2





When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

– WhozCraig
11 hours ago





When my code requires special first-element action (which frankly, I could likely count on one hand the number of times I've needed that in the last five years and still have fingers left over), I don't use ranged-for. I use an iterator, and if-test, and a nested while loop thereafter. The only place that causes headache is when the action taken is a precursor and not an alternative (i.e. the model you're using is such a case: first element gets actions A+B, remaining elements get B, as opposed to first element gets A, remaining get B).

– WhozCraig
11 hours ago




4




4





Possible duplicate of Skipping in Range-based for based on 'index'?

– hlscalon
11 hours ago





Possible duplicate of Skipping in Range-based for based on 'index'?

– hlscalon
11 hours ago




1




1





Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

– bpeikes
7 hours ago





Thanks everyone. I think the a @Ali who posted on stackoverflow.com/questions/21215947/…, had great points. Moving the special case outside of the loop is a much better idea.

– bpeikes
7 hours ago












5 Answers
5






active

oldest

votes


















7














You can't know which element you are visiting in a range based for loop unless you are looping over a container like an array or vector where you can take the address of the object and compare it to the address of the first item to figure out where in the container you are. You can also do this if the container provides lookup by value, you can see if the iterator returned from the find operation is the same as the begin iterator.



If you need special handling for the first element then you can fall back to a traditional for loop like



for (auto it = std::begin(items), first = it, end = std::end(items); it != end; ++it)
{
if (it == first)
{
// do something
}
// Normal processing
}


If what you need to do can be factored out of the loop then you could use a range based for loop and just put the processing before the loop like



// do something
for(const auto &item: items)
{
// Normal processing
}





share|improve this answer





















  • 1





    Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

    – πάντα ῥεῖ
    11 hours ago











  • I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

    – bpeikes
    11 hours ago



















1














A fun alternative solution, that I would not use in production without great care, would be to use custom iterator.



int main() {
std::vector<int> v{1,2,3,4};

for (const auto & [is_first,b] : wrap(v)) {
if (is_first) {
std::cout << "First: ";
}
std::cout << b << std::endl;
}
}


A toy implementation could look like this:



template<typename T>
struct collection_wrap {
collection_wrap(T &c): c_(c) {}

struct magic_iterator {
bool is_first = false;
typename T::iterator itr;

auto operator*() {
return std::make_tuple(is_first, *itr);
}

magic_iterator operator++() {
magic_iterator self = *this;
itr++;
//only works for forward
is_first = false;
return self;
}

bool operator!=(const magic_iterator &o) {
return itr != o.itr;
}
};

magic_iterator begin() {
magic_iterator itr;
itr.is_first = true;
itr.itr = c_.begin();

return itr;
}

magic_iterator end() {
magic_iterator itr;
itr.is_first = false;
itr.itr = c_.end();

return itr;
}


T &c_;
};

template<typename Collection>
collection_wrap<Collection>
wrap(Collection &vec) {
return collection_wrap(vec);
}





share|improve this answer
























  • Is the square bracket a "structured binding"?

    – Costantino Grana
    10 hours ago











  • You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

    – Yankes
    9 hours ago



















1














Maybe a for_first_then_each is what you're looking for? It takes you range in terms of iterators and applies the first function to the first element and the second function to the rest.



#include <iostream>
#include <vector>

template<typename BeginIt, typename EndIt, typename FirstFun, typename OthersFun>
void for_first_then_each(BeginIt begin, EndIt end, FirstFun firstFun, OthersFun othersFun) {
if(begin == end) return;
firstFun(*begin);
for(auto it = std::next(begin); it != end; ++it) {
othersFun(*it);
};
}

int main() {

std::vector<int> v = {0, 1, 2, 3};

for_first_then_each(v.begin(), v.end(),
(auto first) { std::cout << first + 42 << 'n'; },
(auto other) { std::cout << other - 42 << 'n'; }
);

// Outputs 42, -41, -40, -39

return 0;
}





share|improve this answer































    -1














    I think it can be a bit simplified.



       for (const auto &item : items)
    {
    if (&item == &(*std::begin(items)))
    {
    // do something
    }
    // Normal processing
    }





    share|improve this answer





















    • 1





      Not all items containers usable with a range based for loop necessarily implement an access to front().

      – πάντα ῥεῖ
      11 hours ago













    • Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

      – HolyBlackCat
      11 hours ago











    • @HolyBlackCat, I am considering an author question.

      – Dmytro Dadyka
      11 hours ago






    • 1





      This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

      – bpeikes
      11 hours ago











    • if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

      – NathanOliver
      10 hours ago



















    -1














    I assume you want to know how to retrieve the first element, you could do this with an array and a vector.



    I'm going to show the array here.



    First include this in your code:



    #include <array>


    Then convert your array accordingly:



        std::array<std::string, 4> items={"test1", "test2", "test3", "test4"};

    for(const auto &item: items)
    {
    if(item == items.front()){
    // do something
    printf("nFirst: %sn", item.c_str()); //or simply printf("nFirst:"); since you gonna output a double element
    }
    // Normal processing
    printf("Item: %sn", item.c_str());
    }
    return 0;
    }





    share|improve this answer





















    • 2





      Why are you using printf() in c++ code? "Performance" cargo culting?

      – πάντα ῥεῖ
      10 hours ago






    • 4





      @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

      – TonyK
      10 hours ago








    • 1





      Not all items containers usable with a range based for loop necessarily implement an access to front()

      – Dmytro Dadyka
      10 hours ago











    • @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

      – Secko
      10 hours ago











    • I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

      – πάντα ῥεῖ
      10 hours ago











    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%2f54831971%2fc-range-based-loop-with-special-case-for-first-item%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









    7














    You can't know which element you are visiting in a range based for loop unless you are looping over a container like an array or vector where you can take the address of the object and compare it to the address of the first item to figure out where in the container you are. You can also do this if the container provides lookup by value, you can see if the iterator returned from the find operation is the same as the begin iterator.



    If you need special handling for the first element then you can fall back to a traditional for loop like



    for (auto it = std::begin(items), first = it, end = std::end(items); it != end; ++it)
    {
    if (it == first)
    {
    // do something
    }
    // Normal processing
    }


    If what you need to do can be factored out of the loop then you could use a range based for loop and just put the processing before the loop like



    // do something
    for(const auto &item: items)
    {
    // Normal processing
    }





    share|improve this answer





















    • 1





      Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

      – πάντα ῥεῖ
      11 hours ago











    • I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

      – bpeikes
      11 hours ago
















    7














    You can't know which element you are visiting in a range based for loop unless you are looping over a container like an array or vector where you can take the address of the object and compare it to the address of the first item to figure out where in the container you are. You can also do this if the container provides lookup by value, you can see if the iterator returned from the find operation is the same as the begin iterator.



    If you need special handling for the first element then you can fall back to a traditional for loop like



    for (auto it = std::begin(items), first = it, end = std::end(items); it != end; ++it)
    {
    if (it == first)
    {
    // do something
    }
    // Normal processing
    }


    If what you need to do can be factored out of the loop then you could use a range based for loop and just put the processing before the loop like



    // do something
    for(const auto &item: items)
    {
    // Normal processing
    }





    share|improve this answer





















    • 1





      Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

      – πάντα ῥεῖ
      11 hours ago











    • I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

      – bpeikes
      11 hours ago














    7












    7








    7







    You can't know which element you are visiting in a range based for loop unless you are looping over a container like an array or vector where you can take the address of the object and compare it to the address of the first item to figure out where in the container you are. You can also do this if the container provides lookup by value, you can see if the iterator returned from the find operation is the same as the begin iterator.



    If you need special handling for the first element then you can fall back to a traditional for loop like



    for (auto it = std::begin(items), first = it, end = std::end(items); it != end; ++it)
    {
    if (it == first)
    {
    // do something
    }
    // Normal processing
    }


    If what you need to do can be factored out of the loop then you could use a range based for loop and just put the processing before the loop like



    // do something
    for(const auto &item: items)
    {
    // Normal processing
    }





    share|improve this answer















    You can't know which element you are visiting in a range based for loop unless you are looping over a container like an array or vector where you can take the address of the object and compare it to the address of the first item to figure out where in the container you are. You can also do this if the container provides lookup by value, you can see if the iterator returned from the find operation is the same as the begin iterator.



    If you need special handling for the first element then you can fall back to a traditional for loop like



    for (auto it = std::begin(items), first = it, end = std::end(items); it != end; ++it)
    {
    if (it == first)
    {
    // do something
    }
    // Normal processing
    }


    If what you need to do can be factored out of the loop then you could use a range based for loop and just put the processing before the loop like



    // do something
    for(const auto &item: items)
    {
    // Normal processing
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 11 hours ago









    scohe001

    8,07512341




    8,07512341










    answered 11 hours ago









    NathanOliverNathanOliver

    93.2k16130196




    93.2k16130196








    • 1





      Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

      – πάντα ῥεῖ
      11 hours ago











    • I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

      – bpeikes
      11 hours ago














    • 1





      Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

      – πάντα ῥεῖ
      11 hours ago











    • I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

      – bpeikes
      11 hours ago








    1




    1





    Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

    – πάντα ῥεῖ
    11 hours ago





    Your first example could be nicely wrapped into a (algorithm) template taking an iterator range and two std::functions (FirstElementProcessor,, OtherElementProcessor).

    – πάντα ῥεῖ
    11 hours ago













    I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

    – bpeikes
    11 hours ago





    I've thought a template, but I was wondering if there was anything already like this, since it seems to be a common pattern.

    – bpeikes
    11 hours ago













    1














    A fun alternative solution, that I would not use in production without great care, would be to use custom iterator.



    int main() {
    std::vector<int> v{1,2,3,4};

    for (const auto & [is_first,b] : wrap(v)) {
    if (is_first) {
    std::cout << "First: ";
    }
    std::cout << b << std::endl;
    }
    }


    A toy implementation could look like this:



    template<typename T>
    struct collection_wrap {
    collection_wrap(T &c): c_(c) {}

    struct magic_iterator {
    bool is_first = false;
    typename T::iterator itr;

    auto operator*() {
    return std::make_tuple(is_first, *itr);
    }

    magic_iterator operator++() {
    magic_iterator self = *this;
    itr++;
    //only works for forward
    is_first = false;
    return self;
    }

    bool operator!=(const magic_iterator &o) {
    return itr != o.itr;
    }
    };

    magic_iterator begin() {
    magic_iterator itr;
    itr.is_first = true;
    itr.itr = c_.begin();

    return itr;
    }

    magic_iterator end() {
    magic_iterator itr;
    itr.is_first = false;
    itr.itr = c_.end();

    return itr;
    }


    T &c_;
    };

    template<typename Collection>
    collection_wrap<Collection>
    wrap(Collection &vec) {
    return collection_wrap(vec);
    }





    share|improve this answer
























    • Is the square bracket a "structured binding"?

      – Costantino Grana
      10 hours ago











    • You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

      – Yankes
      9 hours ago
















    1














    A fun alternative solution, that I would not use in production without great care, would be to use custom iterator.



    int main() {
    std::vector<int> v{1,2,3,4};

    for (const auto & [is_first,b] : wrap(v)) {
    if (is_first) {
    std::cout << "First: ";
    }
    std::cout << b << std::endl;
    }
    }


    A toy implementation could look like this:



    template<typename T>
    struct collection_wrap {
    collection_wrap(T &c): c_(c) {}

    struct magic_iterator {
    bool is_first = false;
    typename T::iterator itr;

    auto operator*() {
    return std::make_tuple(is_first, *itr);
    }

    magic_iterator operator++() {
    magic_iterator self = *this;
    itr++;
    //only works for forward
    is_first = false;
    return self;
    }

    bool operator!=(const magic_iterator &o) {
    return itr != o.itr;
    }
    };

    magic_iterator begin() {
    magic_iterator itr;
    itr.is_first = true;
    itr.itr = c_.begin();

    return itr;
    }

    magic_iterator end() {
    magic_iterator itr;
    itr.is_first = false;
    itr.itr = c_.end();

    return itr;
    }


    T &c_;
    };

    template<typename Collection>
    collection_wrap<Collection>
    wrap(Collection &vec) {
    return collection_wrap(vec);
    }





    share|improve this answer
























    • Is the square bracket a "structured binding"?

      – Costantino Grana
      10 hours ago











    • You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

      – Yankes
      9 hours ago














    1












    1








    1







    A fun alternative solution, that I would not use in production without great care, would be to use custom iterator.



    int main() {
    std::vector<int> v{1,2,3,4};

    for (const auto & [is_first,b] : wrap(v)) {
    if (is_first) {
    std::cout << "First: ";
    }
    std::cout << b << std::endl;
    }
    }


    A toy implementation could look like this:



    template<typename T>
    struct collection_wrap {
    collection_wrap(T &c): c_(c) {}

    struct magic_iterator {
    bool is_first = false;
    typename T::iterator itr;

    auto operator*() {
    return std::make_tuple(is_first, *itr);
    }

    magic_iterator operator++() {
    magic_iterator self = *this;
    itr++;
    //only works for forward
    is_first = false;
    return self;
    }

    bool operator!=(const magic_iterator &o) {
    return itr != o.itr;
    }
    };

    magic_iterator begin() {
    magic_iterator itr;
    itr.is_first = true;
    itr.itr = c_.begin();

    return itr;
    }

    magic_iterator end() {
    magic_iterator itr;
    itr.is_first = false;
    itr.itr = c_.end();

    return itr;
    }


    T &c_;
    };

    template<typename Collection>
    collection_wrap<Collection>
    wrap(Collection &vec) {
    return collection_wrap(vec);
    }





    share|improve this answer













    A fun alternative solution, that I would not use in production without great care, would be to use custom iterator.



    int main() {
    std::vector<int> v{1,2,3,4};

    for (const auto & [is_first,b] : wrap(v)) {
    if (is_first) {
    std::cout << "First: ";
    }
    std::cout << b << std::endl;
    }
    }


    A toy implementation could look like this:



    template<typename T>
    struct collection_wrap {
    collection_wrap(T &c): c_(c) {}

    struct magic_iterator {
    bool is_first = false;
    typename T::iterator itr;

    auto operator*() {
    return std::make_tuple(is_first, *itr);
    }

    magic_iterator operator++() {
    magic_iterator self = *this;
    itr++;
    //only works for forward
    is_first = false;
    return self;
    }

    bool operator!=(const magic_iterator &o) {
    return itr != o.itr;
    }
    };

    magic_iterator begin() {
    magic_iterator itr;
    itr.is_first = true;
    itr.itr = c_.begin();

    return itr;
    }

    magic_iterator end() {
    magic_iterator itr;
    itr.is_first = false;
    itr.itr = c_.end();

    return itr;
    }


    T &c_;
    };

    template<typename Collection>
    collection_wrap<Collection>
    wrap(Collection &vec) {
    return collection_wrap(vec);
    }






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 11 hours ago









    XaqqXaqq

    3,67821737




    3,67821737













    • Is the square bracket a "structured binding"?

      – Costantino Grana
      10 hours ago











    • You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

      – Yankes
      9 hours ago



















    • Is the square bracket a "structured binding"?

      – Costantino Grana
      10 hours ago











    • You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

      – Yankes
      9 hours ago

















    Is the square bracket a "structured binding"?

    – Costantino Grana
    10 hours ago





    Is the square bracket a "structured binding"?

    – Costantino Grana
    10 hours ago













    You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

    – Yankes
    9 hours ago





    You should add template<typename T> void warp(T&& t) = delete; to prevent use of dangling references

    – Yankes
    9 hours ago











    1














    Maybe a for_first_then_each is what you're looking for? It takes you range in terms of iterators and applies the first function to the first element and the second function to the rest.



    #include <iostream>
    #include <vector>

    template<typename BeginIt, typename EndIt, typename FirstFun, typename OthersFun>
    void for_first_then_each(BeginIt begin, EndIt end, FirstFun firstFun, OthersFun othersFun) {
    if(begin == end) return;
    firstFun(*begin);
    for(auto it = std::next(begin); it != end; ++it) {
    othersFun(*it);
    };
    }

    int main() {

    std::vector<int> v = {0, 1, 2, 3};

    for_first_then_each(v.begin(), v.end(),
    (auto first) { std::cout << first + 42 << 'n'; },
    (auto other) { std::cout << other - 42 << 'n'; }
    );

    // Outputs 42, -41, -40, -39

    return 0;
    }





    share|improve this answer




























      1














      Maybe a for_first_then_each is what you're looking for? It takes you range in terms of iterators and applies the first function to the first element and the second function to the rest.



      #include <iostream>
      #include <vector>

      template<typename BeginIt, typename EndIt, typename FirstFun, typename OthersFun>
      void for_first_then_each(BeginIt begin, EndIt end, FirstFun firstFun, OthersFun othersFun) {
      if(begin == end) return;
      firstFun(*begin);
      for(auto it = std::next(begin); it != end; ++it) {
      othersFun(*it);
      };
      }

      int main() {

      std::vector<int> v = {0, 1, 2, 3};

      for_first_then_each(v.begin(), v.end(),
      (auto first) { std::cout << first + 42 << 'n'; },
      (auto other) { std::cout << other - 42 << 'n'; }
      );

      // Outputs 42, -41, -40, -39

      return 0;
      }





      share|improve this answer


























        1












        1








        1







        Maybe a for_first_then_each is what you're looking for? It takes you range in terms of iterators and applies the first function to the first element and the second function to the rest.



        #include <iostream>
        #include <vector>

        template<typename BeginIt, typename EndIt, typename FirstFun, typename OthersFun>
        void for_first_then_each(BeginIt begin, EndIt end, FirstFun firstFun, OthersFun othersFun) {
        if(begin == end) return;
        firstFun(*begin);
        for(auto it = std::next(begin); it != end; ++it) {
        othersFun(*it);
        };
        }

        int main() {

        std::vector<int> v = {0, 1, 2, 3};

        for_first_then_each(v.begin(), v.end(),
        (auto first) { std::cout << first + 42 << 'n'; },
        (auto other) { std::cout << other - 42 << 'n'; }
        );

        // Outputs 42, -41, -40, -39

        return 0;
        }





        share|improve this answer













        Maybe a for_first_then_each is what you're looking for? It takes you range in terms of iterators and applies the first function to the first element and the second function to the rest.



        #include <iostream>
        #include <vector>

        template<typename BeginIt, typename EndIt, typename FirstFun, typename OthersFun>
        void for_first_then_each(BeginIt begin, EndIt end, FirstFun firstFun, OthersFun othersFun) {
        if(begin == end) return;
        firstFun(*begin);
        for(auto it = std::next(begin); it != end; ++it) {
        othersFun(*it);
        };
        }

        int main() {

        std::vector<int> v = {0, 1, 2, 3};

        for_first_then_each(v.begin(), v.end(),
        (auto first) { std::cout << first + 42 << 'n'; },
        (auto other) { std::cout << other - 42 << 'n'; }
        );

        // Outputs 42, -41, -40, -39

        return 0;
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 9 hours ago









        Joakim ThorénJoakim Thorén

        6428




        6428























            -1














            I think it can be a bit simplified.



               for (const auto &item : items)
            {
            if (&item == &(*std::begin(items)))
            {
            // do something
            }
            // Normal processing
            }





            share|improve this answer





















            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front().

              – πάντα ῥεῖ
              11 hours ago













            • Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

              – HolyBlackCat
              11 hours ago











            • @HolyBlackCat, I am considering an author question.

              – Dmytro Dadyka
              11 hours ago






            • 1





              This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

              – bpeikes
              11 hours ago











            • if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

              – NathanOliver
              10 hours ago
















            -1














            I think it can be a bit simplified.



               for (const auto &item : items)
            {
            if (&item == &(*std::begin(items)))
            {
            // do something
            }
            // Normal processing
            }





            share|improve this answer





















            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front().

              – πάντα ῥεῖ
              11 hours ago













            • Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

              – HolyBlackCat
              11 hours ago











            • @HolyBlackCat, I am considering an author question.

              – Dmytro Dadyka
              11 hours ago






            • 1





              This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

              – bpeikes
              11 hours ago











            • if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

              – NathanOliver
              10 hours ago














            -1












            -1








            -1







            I think it can be a bit simplified.



               for (const auto &item : items)
            {
            if (&item == &(*std::begin(items)))
            {
            // do something
            }
            // Normal processing
            }





            share|improve this answer















            I think it can be a bit simplified.



               for (const auto &item : items)
            {
            if (&item == &(*std::begin(items)))
            {
            // do something
            }
            // Normal processing
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 10 hours ago

























            answered 11 hours ago









            Dmytro DadykaDmytro Dadyka

            8121618




            8121618








            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front().

              – πάντα ῥεῖ
              11 hours ago













            • Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

              – HolyBlackCat
              11 hours ago











            • @HolyBlackCat, I am considering an author question.

              – Dmytro Dadyka
              11 hours ago






            • 1





              This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

              – bpeikes
              11 hours ago











            • if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

              – NathanOliver
              10 hours ago














            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front().

              – πάντα ῥεῖ
              11 hours ago













            • Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

              – HolyBlackCat
              11 hours ago











            • @HolyBlackCat, I am considering an author question.

              – Dmytro Dadyka
              11 hours ago






            • 1





              This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

              – bpeikes
              11 hours ago











            • if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

              – NathanOliver
              10 hours ago








            1




            1





            Not all items containers usable with a range based for loop necessarily implement an access to front().

            – πάντα ῥεῖ
            11 hours ago







            Not all items containers usable with a range based for loop necessarily implement an access to front().

            – πάντα ῥεῖ
            11 hours ago















            Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

            – HolyBlackCat
            11 hours ago





            Also this looks somewhat brittle to me. If someone replaces const auto &item with auto, it will silently break.

            – HolyBlackCat
            11 hours ago













            @HolyBlackCat, I am considering an author question.

            – Dmytro Dadyka
            11 hours ago





            @HolyBlackCat, I am considering an author question.

            – Dmytro Dadyka
            11 hours ago




            1




            1





            This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

            – bpeikes
            11 hours ago





            This seems expensive, and introduces iterators, which is what you're trying to hide by using a range based loop.

            – bpeikes
            11 hours ago













            if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

            – NathanOliver
            10 hours ago





            if (&item == &(*items.begin())) is also not going to work. if items is a raw array there is no begin member function.

            – NathanOliver
            10 hours ago











            -1














            I assume you want to know how to retrieve the first element, you could do this with an array and a vector.



            I'm going to show the array here.



            First include this in your code:



            #include <array>


            Then convert your array accordingly:



                std::array<std::string, 4> items={"test1", "test2", "test3", "test4"};

            for(const auto &item: items)
            {
            if(item == items.front()){
            // do something
            printf("nFirst: %sn", item.c_str()); //or simply printf("nFirst:"); since you gonna output a double element
            }
            // Normal processing
            printf("Item: %sn", item.c_str());
            }
            return 0;
            }





            share|improve this answer





















            • 2





              Why are you using printf() in c++ code? "Performance" cargo culting?

              – πάντα ῥεῖ
              10 hours ago






            • 4





              @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

              – TonyK
              10 hours ago








            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front()

              – Dmytro Dadyka
              10 hours ago











            • @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

              – Secko
              10 hours ago











            • I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

              – πάντα ῥεῖ
              10 hours ago
















            -1














            I assume you want to know how to retrieve the first element, you could do this with an array and a vector.



            I'm going to show the array here.



            First include this in your code:



            #include <array>


            Then convert your array accordingly:



                std::array<std::string, 4> items={"test1", "test2", "test3", "test4"};

            for(const auto &item: items)
            {
            if(item == items.front()){
            // do something
            printf("nFirst: %sn", item.c_str()); //or simply printf("nFirst:"); since you gonna output a double element
            }
            // Normal processing
            printf("Item: %sn", item.c_str());
            }
            return 0;
            }





            share|improve this answer





















            • 2





              Why are you using printf() in c++ code? "Performance" cargo culting?

              – πάντα ῥεῖ
              10 hours ago






            • 4





              @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

              – TonyK
              10 hours ago








            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front()

              – Dmytro Dadyka
              10 hours ago











            • @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

              – Secko
              10 hours ago











            • I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

              – πάντα ῥεῖ
              10 hours ago














            -1












            -1








            -1







            I assume you want to know how to retrieve the first element, you could do this with an array and a vector.



            I'm going to show the array here.



            First include this in your code:



            #include <array>


            Then convert your array accordingly:



                std::array<std::string, 4> items={"test1", "test2", "test3", "test4"};

            for(const auto &item: items)
            {
            if(item == items.front()){
            // do something
            printf("nFirst: %sn", item.c_str()); //or simply printf("nFirst:"); since you gonna output a double element
            }
            // Normal processing
            printf("Item: %sn", item.c_str());
            }
            return 0;
            }





            share|improve this answer















            I assume you want to know how to retrieve the first element, you could do this with an array and a vector.



            I'm going to show the array here.



            First include this in your code:



            #include <array>


            Then convert your array accordingly:



                std::array<std::string, 4> items={"test1", "test2", "test3", "test4"};

            for(const auto &item: items)
            {
            if(item == items.front()){
            // do something
            printf("nFirst: %sn", item.c_str()); //or simply printf("nFirst:"); since you gonna output a double element
            }
            // Normal processing
            printf("Item: %sn", item.c_str());
            }
            return 0;
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 9 hours ago

























            answered 10 hours ago









            SeckoSecko

            5,47532433




            5,47532433








            • 2





              Why are you using printf() in c++ code? "Performance" cargo culting?

              – πάντα ῥεῖ
              10 hours ago






            • 4





              @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

              – TonyK
              10 hours ago








            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front()

              – Dmytro Dadyka
              10 hours ago











            • @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

              – Secko
              10 hours ago











            • I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

              – πάντα ῥεῖ
              10 hours ago














            • 2





              Why are you using printf() in c++ code? "Performance" cargo culting?

              – πάντα ῥεῖ
              10 hours ago






            • 4





              @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

              – TonyK
              10 hours ago








            • 1





              Not all items containers usable with a range based for loop necessarily implement an access to front()

              – Dmytro Dadyka
              10 hours ago











            • @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

              – Secko
              10 hours ago











            • I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

              – πάντα ῥεῖ
              10 hours ago








            2




            2





            Why are you using printf() in c++ code? "Performance" cargo culting?

            – πάντα ῥεῖ
            10 hours ago





            Why are you using printf() in c++ code? "Performance" cargo culting?

            – πάντα ῥεῖ
            10 hours ago




            4




            4





            @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

            – TonyK
            10 hours ago







            @πάνταῥεῖ: I use printf all the time in my C++ code. I'm allowed to, and I prefer it, and it works, so who are you to judge me?

            – TonyK
            10 hours ago






            1




            1





            Not all items containers usable with a range based for loop necessarily implement an access to front()

            – Dmytro Dadyka
            10 hours ago





            Not all items containers usable with a range based for loop necessarily implement an access to front()

            – Dmytro Dadyka
            10 hours ago













            @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

            – Secko
            10 hours ago





            @πάνταῥεῖ Yeah, I like printf more, what can you do. Didn't know people downvoted for that. :D

            – Secko
            10 hours ago













            I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

            – πάντα ῥεῖ
            10 hours ago





            I didn't downvote, and certainly not for that. I've just been asking, because it's unusual to see in clean c++ code. Also cargo cult programming is a well established term in modern software development.

            – πάντα ῥεῖ
            10 hours ago


















            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%2f54831971%2fc-range-based-loop-with-special-case-for-first-item%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

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            Origin of the phrase “under your belt”?