Modern C++ way to repeat code for set number of times

十年热恋 提交于 2020-01-15 03:24:11

问题


Very simply, is there a simpler way to repeat a block for a certain number of times, where the block inside does not need the counter variable? The trivial solution is of course

for (int i = 0; i < repetitions; ++i) {
  //do your thing, i is not used here
}

However, now that we have ranged for, standard algorithms and other fancy constructs for iterating over containers, in comparison this is actually starting to feel like a lot of boilerplate and details for what should be an even simpler case. For example we're not interested in the variable i at all etc.

The closest thing to a concrete problem is this: when I encounter a for loop such as above, I need to scan through the code block to see if i is actually used, or if it's just a dummy counter. The declaration of a for loop which actually wants to do something with the integers 0 to repetitions - 1 will look identical. So a repeat (n) -type construct would have the extra semantic information that all the iterations will be the same, except for potential side-effects.

One option is to make a template

template<class functor>
repeat(functor fun, unsigned n) {
   for (unsigned i = 0; i < n; ++i)
     fun();
}

and call

repeat([&](){
  //do your thing
}, repetitions)

but this really seems like overengineered overkill for a simple problem. This could be macroized to make the usage a bit nicer, but that certainly won't help with the overengineered feel.

So one valid answer is that I'm on a wild goose chase here, and should just use the good old for loop with counter.

Any standard C++ is fine, including upcoming standards.

Related questions such as How to create a loop in C++ that loops a certain amount of times? and How to create a loop in C++ that loops a certain amount of times? are beginners asking for some way to achieve this, whereas I'm specifically asking for a modern, clean and elegant way to achieve this. c++ repeat N iterations is very close, though the difference here is that I'm asking for any alternatives, not necessarily included in std::.


回答1:


Instead of a modern C++ way, how about an old C way but without an index:

while (repetitions--)
    fun();

Of course you still need a variable for repetitions though.




回答2:


Introduction

Modern does not necessarily means using newest feautures.

Solution

One of the easiest solutions it to use simple for loop as below:

for (auto _ = times; _--;) [[likely]] statement;

…where:

  • times is a constant integer literal with no suffix (ie 3).
  • statement is a statement to be executed times times.

Example

Example usage:

constexpr auto f(int Value) noexcept
{
    for (auto _ = 3; _--;) [[likely]] ++Value;
    return Value;
}

int main()
{
    constexpr auto i = f(2);
    return i;
}

Constant i variable is declared with initial value of 2, increased 3 times by one in f's for loop, taking final value of 5 and being used as program returned value.

Notes

  • Some compiler implementations may potentially take use of [[likely]] attribute in future.
    If times constant is likely to be zero, use [[unlikely]] attribute instead.
    Likelihood attribute is a c++20 feauture, skip in earlier versions.
  • _ name is commonly used as meaningless to name a discardable variable.



回答3:


"Hand-made" repeat is somewhat problematic. Should there be break or continue? One can throw an exception from "inside" repat, and "break out". But some projects do disallow exceptions.

Also in the presence of a standard for range loop one does not need to "scan through the code block to see if i is actually used, or if it's just a dummy counter.". That argument is done with.

To have compiler intrinsic repeat might be not such a bad idea, and certainly would be easy to add.

    // C++ 25 -- perhaps 
    repeat( 42 ) {
        std::printf("\nThis is 42 lines of text.");
        continue; // allowed
        break ;   // allowed
    }

REPEAT(N) macro is tempting, but macros are forbiden. If not compiler intrinsic, user defined repeat is not that "simple and elegant". Here is what I might be using:

// the repeat
template< typename CALLABLE_, typename ... Args >
void repeat( size_t N, CALLABLE_ fun_, Args ... args)
{
    for ( auto k = 0 ; k <  N ; k++ ) {
        fun_(args ...);
    }
}

Now to use the above one would most likely call it with lambda. Usage is as expected:

// reachable from inside `repeat`
int result {} ;

repeat( 0xF ,  
 [&] {  
     ::std::wprintf( L"\n random word:\t '%s'", random_word());
     result++ ;
    }
 );

The "modern way" is not always "the elegant vintage way".



来源:https://stackoverflow.com/questions/55530455/modern-c-way-to-repeat-code-for-set-number-of-times

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!