: , . , . , .
, , C++. , :
for (int i=0; i<size; i++) {
[...]
}
, :
find . \( -name \*.h -o -name \*.cpp \) -exec grep -H "for (" {} \; | wc -l
43641
43 . , (, , ), . for ? , , , , (. code review). .
« » (perfection loop).

, ?
?
; , , , . , :
for (int iter=0; iter<nb_iter; iter++) { // some iterative computation
for (int c=0; c<mesh.cells.nb(); c++) // loop through all tetrahedra
for (int lv0=0; lv0<4; lv0++) // for every pair of
for (int lv1 = lv0+1; lv1<4; lv1++) // vertices in the tet
for (int d=0; d<3; d++) { // do stuff for each of 3 dimensions
nlRowScaling(weight);
nlBegin(NL_ROW);
nlCoefficient(mesh.cells.vertex(c, lv0)*3 + d, 1);
nlCoefficient(mesh.cells.vertex(c, lv1)*3 + d, -1);
nlEnd(NL_ROW);
}
[...]
}
, , . , , --, .
; . ( ) , for (int i=0; i<size; i++) — : for , .
for(;;), : , . , 0 size-1, . , ? , — .
c++11 , :
#define FOR(I,UPPERBND) for(int I = 0; I<int(UPPERBND); ++I)
:
FOR(iter, nb_iter) {
FOR(c, mesh.cells.nb())
FOR(lv0, 4)
for (int lv1 = lv0+1; lv1<4; lv1++)
FOR(d, 3) {
nlRowScaling(weight);
nlBegin(NL_ROW);
nlCoefficient(mesh.cells.vertex(c, lv0)*3 + d, 1);
nlCoefficient(mesh.cells.vertex(c, lv1)*3 + d, -1);
nlEnd(NL_ROW);
}
[...]
}
, for (;;), , (, , ). FOR(,) 0 n-1 - . , , , (. ), (, , ).
, , , : " , ?"
11 , range for
? , . , :
for i in range(n):
print(i)
, range() , . c++11 !
#include <iostream>
int main() {
int range[] = {0,1,2,3,4,5};
for (int i : range) {
std::cerr << i;
}
}
, , . C++ !
range(int n):
#include <iostream>
constexpr auto range(int n) {
struct iterator {
int i;
void operator++() { ++i; }
bool operator!=(const iterator& rhs) const { return i != rhs.i; }
const int &operator*() const { return i; }
};
struct wrapper {
int n;
auto begin() { return iterator{0}; }
auto end() { return iterator{n}; }
};
return wrapper{n};
}
int main() {
for (int i: range(13)) {
std::cerr << i;
}
return 0;
}
, int vs size_t, . gcc 10.2 -std=c++17 -Wall -Wextra -pedantic -O1, ( ):
[...]
.L2:
mov esi, ebx
mov edi, OFFSET FLAT:_ZSt4cerr
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
add ebx, 1
cmp ebx, 13
jne .L2
[...]
, , for (int i=0; i<13; i++).
, for (int i: range(n)) , FOR(,), , .
: enumerate
Range for c++11 . , , , :
#include <vector>
#include <iostream>
struct vec3 { double x,y,z; };
int main() {
std::vector<vec3> points = {{6,5,8},{1,2,3},{7,3,7}};
for (vec3 &p: points) {
std::cerr << p.x;
}
return 0;
}
for (vec3 &p: points) , , . , ? , . , , , :
std::vector<vec3> points = {{6,5,8},{1,2,3},{7,3,7}};
std::vector<double> weights = {4,6,9};
int i = 0;
for (vec3 &p: points) {
std::cerr << p.x << weights[i++];
}
:
.L2:
movsd xmm0, QWORD PTR [r13+0]
mov edi, OFFSET FLAT:_ZSt4cerr
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
movsd xmm0, QWORD PTR [rbp+0]
mov rdi, rax
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
add rbp, 8
add r13, 24
cmp r14, rbp
jne .L2, , , , , c++17 structural binding!
, :
#include <vector>
#include <iostream>
#include "range.h"
struct vec3 {
double x,y,z;
};
int main() {
std::vector<vec3> points = {{6,5,8},{1,2,3},{7,3,7}};
std::vector<double> weights = {4,6,9};
for (auto [i, p]: enumerate(points)) {
std::cerr << p.x << weights[i];
}
return 0;
}
enumerate() :
#ifndef __RANGE_H__
#define __RANGE_H__
#include <tuple>
#include <utility>
#include <iterator>
constexpr auto range(int n) {
struct iterator {
int i;
void operator++() { ++i; }
bool operator!=(const iterator& rhs) const { return i != rhs.i; }
const int &operator*() const { return i; }
};
struct wrapper {
int n;
auto begin() { return iterator{0}; }
auto end() { return iterator{n}; }
};
return wrapper{n};
}
template <typename T> constexpr auto enumerate(T && iterable) {
struct iterator {
int i;
typedef decltype(std::begin(std::declval<T>())) iterator_type;
iterator_type iter;
bool operator!=(const iterator& rhs) const { return iter != rhs.iter; }
void operator++() { ++i; ++iter; }
auto operator*() const { return std::tie(i, *iter); }
};
struct wrapper {
T iterable;
auto begin() { return iterator{0, std::begin(iterable)}; }
auto end() { return iterator{0, std::end (iterable)}; }
};
return wrapper{std::forward<T>(iterable)};
}
#endif // __RANGE_H__ -std=c++17 -Wall -Wextra -pedantic -O2 ( ):
.L14:
movsd xmm0, QWORD PTR [rbx]
mov edi, OFFSET FLAT:_ZSt4cerr
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
mov rdi, rax
mov rax, QWORD PTR [rsp+32]
movsd xmm0, QWORD PTR [rax+rbp]
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
add rbx, 24
add rbp, 8
cmp r12, rbx
jne .L14 (, -O1 -O2).
, c++20 std::ranges, , .
, 2020 ? !
, - range.h .