3

My program has an iterative algorithm with a for-loop that I had written as

for ( auto i: std::views::iota( 0u, max_iter ) ) { ... }

I really like the fact that it can be written like this, even if the necessary header files are enormous. When I compile it though I get a warning that i is an unused variable.

When I write the for-loop in the old-fashioned way

for ( unsigned i=0; i < max_iter; i++ ) { ... }

then there is no warning.

I tested this with a minimal program for-loop.cpp:

#include<ranges>
#include<numeric>
#include<iostream>

int main() {

    char str[13] = "this is good";

    for (auto i : std::views::iota(0u, 2u)) {
        std::cout << str << "\n";
    }
  
    for (unsigned it=0; it<2; it++ ) {
        std::cout << str << "\n";
    }

    return 0; 
} 

and sure enough, compiling it with g++ -Wall --std=c++20 -o for-loop for-loop.cpp gives a warning for the first loop and not the second.

Am I missing something here? I prefer the first notation -- and I know that I can stop the warnings wit -Wno-unused-variables; I would like those warnings, it's just that I am really using the for-loop counter.

user438383
  • 5,716
  • 8
  • 28
  • 43
alle_meije
  • 2,424
  • 1
  • 19
  • 40
  • In the second example `i` is considered "used" in the loop boundary check and the loop increment. Do you still get the warning if you rename `i` to `_` in the first example? – 0x5453 Jan 07 '22 at 14:25
  • Also consider using `[[maybe_unused]]` instead of disabling the warning globally in general. Although not in that case, renaming `i` to `_` should be sufficient. – Tommy-Xavier Robillard Jan 07 '22 at 14:26
  • 1
    @0x5453 - Yes, then it gives the warning for the name '_' – alle_meije Jan 07 '22 at 14:27
  • Does `while (std::views::iota( 0u, max_iter ) ) { ... }` give you the same unused variable warning? – Stephen M. Webb Jan 07 '22 at 14:28
  • @Tommy-XavierRobillard ah yes, `[[maybe_unused]]` does the trick! I did not know that syntax, thanks very much! – alle_meije Jan 07 '22 at 14:34
  • 2
    `for ( auto i: std::views::iota( 0u, max_iter ) ) { ... }` seems very complicated, harder to read, understand and maintain compared to the corresponding plain `for` loop. A programmers primary goal (IMO) should be good, clean, readable, easily understandable, and maintainable code. But most importantly it should be *simple*. – Some programmer dude Jan 07 '22 at 14:37
  • @StephenM.Webb - that gives an error that there is `no viable conversion` from the range to a boolean – alle_meije Jan 07 '22 at 14:37
  • An idiomatic way of making a variable "used" with no side effect is to cast it to void. Adding `(void)i;` inside the loop body will fix this kind of problem in every version of C++. – François Andrieux Jan 07 '22 at 14:37
  • @Someprogrammerdude I came across this notation when I was looking for a way to write a loop more similar to python (or matlab). Other than the scope identifiers that make it a bit longer, I think it is a very readable notation. To me the fact that `i` only appears once in there makes sense. – alle_meije Jan 07 '22 at 14:47

2 Answers2

4

i is indeed never used.

You might add attribute [[maybe_unused]] (C++17) to ignore that warning:

for ([[maybe_unused]]auto i : std::views::iota(0u, 2u)) {
    std::cout << str << "\n";
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
2

With the auto i you never use the variable anywhere.

With the for ( unsigned i=0; i < max_iter; i++ ) you're using i twice, once in i < max_iter and again in i++ so the variable is used

Sean
  • 60,939
  • 11
  • 97
  • 136