现代C ++方式重复设置次数的代码

时间:2019-04-05 07:38:31

标签: c++ loops c++17 c++20

很简单,是否有一种更简单的方法可以将某个块重复一定次数,而其中的块不需要计数器变量?平凡的解决方案当然是

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

但是,既然我们已经找到了用于遍历容器的标准算法和其他奇特的构造,那么相比之下,这实际上开始感觉像是很多样板和细节,甚至应该是更简单的情况。例如,我们对变量i完全不感兴趣,等等。

与具体问题最接近的事情是:当我遇到上述的for循环时,我需要遍历代码块以查看是否实际使用i,或者它只是一个虚拟计数器。 。 for循环的声明实际上想要用0到repetitions - 1的整数来表示,这看起来是相同的。因此,repeat (n)型构造将具有额外的语义信息,除了潜在的副作用外,所有迭代都将是相同的。

一种选择是制作模板

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

并致电

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

但是对于一个简单的问题,这似乎确实是过度设计的过度杀伤力。可以对它进行宏化处理,以使其使用起来更好一些,但是对于过度设计的感觉当然不会有所帮助。

一个有效的答案是,我在这里追逐野鹅,应该使用带有计数器的好for循环。

任何标准C ++都可以,包括即将发布的标准。

诸如How to create a loop in C++ that loops a certain amount of times?How to create a loop in C++ that loops a certain amount of times?之类的相关问题是初学者,他们要求某种方式来实现这一目标,而我特别要求一种现代,干净且优雅的方式来实现这一目标。 c++ repeat N iterations非常接近,尽管这里的区别在于我要求的是任何其他替代品,不一定包含在std::中。

3 个答案:

答案 0 :(得分:3)

代替现代的C ++方式,如何使用旧的C方式却没有索引:

while (repetitions--)
    fun();

当然,repetitions仍然需要一个变量。

答案 1 :(得分:1)

简介

现代不一定意味着要使用最新功能。

解决方案

最简单的解决方案之一是使用简单的for循环,如下所示:

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

…其中:

示例

用法示例:

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

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

常量i声明为初始值2,在f的{​​{1}}循环中加3倍,取最终值{{1} },并用作程序的返回值。

注释

  • 某些编译器实现将来可能会使用[[likely]]属性。
    如果for常数很可能为零,请改用5属性。
    可能性属性是的一项功能,请在早期版本中跳过。
  • times名称通常无意义地用于命名可丢弃变量。

答案 2 :(得分:0)

“手工制作” repeat有点问题。应该有breakcontinue吗?可以从“内部”重传和“爆发”中引发异常。但是某些项目确实不允许例外。

在存在标准for range loop的情况下,也不需要“ 扫描代码块以查看i是否实际使用,或者它只是一个虚拟计数器。” 。该论点是用完的。

拥有内置的编译器repeat可能不是一个坏主意,并且肯定很容易添加。

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

REPEAT(N)宏很吸引人,但是禁止使用宏。如果不是编译器固有的,则用户定义的repeat并非“简单而优雅”。这是我可能正在使用的:

// 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 ...);
    }
}

现在使用以上代码很可能将其称为lambda。使用情况符合预期:

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

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

“现代方式”并不总是“优雅的复古方式”。