现代C++中重复执行一段代码固定次数的方法

12

简单明了,有没有更简单的方法来重复一个块一定次数,而内部块不需要计数变量?当然,微不足道的解决方案是

for (int i = 0; i < repetitions; ++i) {
  //do your thing, i is not used here
}
然而,现在我们有了range for、标准算法和其他复杂的结构来迭代容器,相比之下,这实际上开始感觉像是很多模板和细节,对于一个本应该更简单的情况。例如,我们根本不关心变量 i 等等。

最接近具体问题的事情是:当我遇到像上面那样的for循环时,我需要扫描代码块以查看 i 是否实际使用,还是仅仅是虚拟计数器。实际想要处理0到 repetitions - 1 之间的整数的for循环声明将看起来完全相同。因此,类似于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++都可以,包括即将到来的标准。

相关问题,如如何在C++中创建循环以重复指定次数?如何在C++中创建循环以重复指定次数?是初学者寻求某种方法来实现此目的,而我特别要求以一种现代化、干净和优雅的方式实现此目的。c++重复N次迭代非常接近,但这里的区别在于我要求任何替代方案,不一定包括std::


9
可能是c++ repeat N iterations的重复问题。 - cfillion
3
好的...一个简单的抽象循环的函数可能就足够了。但我仍然认为使用老式可靠的循环也没有问题。 - Netwave
6
普通循环有任何问题吗?C++甚至允许在其中声明计数器。 - user7860670
1
@VTT 不,当然没有实际问题。这更多是关于我自己纠结于尝试用最简单的方式编写代码,以最直接地表达意图。 - Timo
2
@Timo说:“用最简单的方式写出表达意图最直接的东西” - 那么你肯定应该尝试使用COBOL: Perform something 5 times. - user7860670
显示剩余6条评论
3个回答

6

介绍

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

解决方案

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

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

…其中:

  • times 是一个没有后缀的常量整数字面量(例如3)。
  • statement 是要执行times次的语句

示例

用法示例:

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

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

常量i变量被声明为初始值为2,在ffor循环中增加了3次1,取得了最终值5并被用作程序的返回值。

注释

  • 一些编译器实现可能会在将来利用[[likely]]属性。
    如果times常量可能为零,请改用[[unlikely]]属性。
    Likelihood属性是功能,在较早版本中跳过。
  • _名称通常用于命名可丢弃的变量。

5

不要使用现代C++,可以使用旧的C方式,但不需要索引:

while (repetitions--)
    fun();

当然,你仍然需要一个变量来表示 repetitions


6
repetitions 是一个指数。 - user7860670
7
请问需要翻译的内容是什么呢? - YSC
在我看来,定义一个计数器与人类思维完全不一致。我就 https://stackoverflow.com/questions/55654319/why-c-has-no-concise-syntax-that-allow-executing-an-operation-multiple-times-w 相关问题提出了我的建议。 - Crawl.W

0
手写的repeat有些问题。应该使用break还是continue?可以从“内部”重复抛出异常并“中断”。但是一些项目不允许异常。
此外,在存在标准的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++ ;
    }
 );

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接