From Jason Turner

[ranges]

Large diff (168.8 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpe0t9igkm/{from.md → to.md} +5338 -0
tmp/tmpe0t9igkm/{from.md → to.md} RENAMED
@@ -0,0 +1,5338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ranges library <a id="ranges">[[ranges]]</a>
2
+
3
+ ## General <a id="ranges.general">[[ranges.general]]</a>
4
+
5
+ This clause describes components for dealing with ranges of elements.
6
+
7
+ The following subclauses describe range and view requirements, and
8
+ components for range primitives as summarized in [[range.summary]].
9
+
10
+ **Table: Ranges library summary** <a id="range.summary">[range.summary]</a>
11
+
12
+ | Subclause | | Header |
13
+ | ------------------- | --------------- | ---------- |
14
+ | [[range.access]] | Range access | `<ranges>` |
15
+ | [[range.req]] | Requirements | |
16
+ | [[range.utility]] | Range utilities | |
17
+ | [[range.factories]] | Range factories | |
18
+ | [[range.adaptors]] | Range adaptors | |
19
+
20
+
21
+ ## Header `<ranges>` synopsis <a id="ranges.syn">[[ranges.syn]]</a>
22
+
23
+ ``` cpp
24
+ #include <compare> // see [compare.syn]
25
+ #include <initializer_list> // see [initializer.list.syn]
26
+ #include <iterator> // see [iterator.synopsis]
27
+
28
+ namespace std::ranges {
29
+ inline namespace unspecified {
30
+ // [range.access], range access
31
+ inline constexpr unspecified begin = unspecified;
32
+ inline constexpr unspecified end = unspecified;
33
+ inline constexpr unspecified cbegin = unspecified;
34
+ inline constexpr unspecified cend = unspecified;
35
+ inline constexpr unspecified rbegin = unspecified;
36
+ inline constexpr unspecified rend = unspecified;
37
+ inline constexpr unspecified crbegin = unspecified;
38
+ inline constexpr unspecified crend = unspecified;
39
+
40
+ inline constexpr unspecified size = unspecified;
41
+ inline constexpr unspecified ssize = unspecified;
42
+ inline constexpr unspecified empty = unspecified;
43
+ inline constexpr unspecified data = unspecified;
44
+ inline constexpr unspecified cdata = unspecified;
45
+ }
46
+
47
+ // [range.range], ranges
48
+ template<class T>
49
+ concept range = see below;
50
+
51
+ template<class T>
52
+ inline constexpr bool enable_borrowed_range = false;
53
+
54
+ template<class T>
55
+ concept borrowed_range = see below;
56
+
57
+ template<class T>
58
+ using iterator_t = decltype(ranges::begin(declval<T&>()));
59
+ template<range R>
60
+ using sentinel_t = decltype(ranges::end(declval<R&>()));
61
+ template<range R>
62
+ using range_difference_t = iter_difference_t<iterator_t<R>>;
63
+ template<sized_range R>
64
+ using range_size_t = decltype(ranges::size(declval<R&>()));
65
+ template<range R>
66
+ using range_value_t = iter_value_t<iterator_t<R>>;
67
+ template<range R>
68
+ using range_reference_t = iter_reference_t<iterator_t<R>>;
69
+ template<range R>
70
+ using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
71
+
72
+ // [range.sized], sized ranges
73
+ template<class>
74
+ inline constexpr bool disable_sized_range = false;
75
+
76
+ template<class T>
77
+ concept sized_range = see below;
78
+
79
+ // [range.view], views
80
+ template<class T>
81
+ inline constexpr bool enable_view = see below;
82
+
83
+ struct view_base { };
84
+
85
+ template<class T>
86
+ concept view = see below;
87
+
88
+ // [range.refinements], other range refinements
89
+ template<class R, class T>
90
+ concept output_range = see below;
91
+
92
+ template<class T>
93
+ concept input_range = see below;
94
+
95
+ template<class T>
96
+ concept forward_range = see below;
97
+
98
+ template<class T>
99
+ concept bidirectional_range = see below;
100
+
101
+ template<class T>
102
+ concept random_access_range = see below;
103
+
104
+ template<class T>
105
+ concept contiguous_range = see below;
106
+
107
+ template<class T>
108
+ concept common_range = see below;
109
+
110
+ template<class T>
111
+ concept viewable_range = see below;
112
+
113
+ // [view.interface], class template view_interface
114
+ template<class D>
115
+ requires is_class_v<D> && same_as<D, remove_cv_t<D>>
116
+ class view_interface;
117
+
118
+ // [range.subrange], sub-ranges
119
+ enum class subrange_kind : bool { unsized, sized };
120
+
121
+ template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = see below>
122
+ requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
123
+ class subrange;
124
+
125
+ template<input_or_output_iterator I, sentinel_for<I> S, subrange_kind K>
126
+ inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
127
+
128
+ // [range.dangling], dangling iterator handling
129
+ struct dangling;
130
+
131
+ template<range R>
132
+ using borrowed_iterator_t = conditional_t<borrowed_range<R>, iterator_t<R>, dangling>;
133
+
134
+ template<range R>
135
+ using borrowed_subrange_t =
136
+ conditional_t<borrowed_range<R>, subrange<iterator_t<R>>, dangling>;
137
+
138
+ // [range.empty], empty view
139
+ template<class T>
140
+ requires is_object_v<T>
141
+ class empty_view;
142
+
143
+ template<class T>
144
+ inline constexpr bool enable_borrowed_range<empty_view<T>> = true;
145
+
146
+ namespace views {
147
+ template<class T>
148
+ inline constexpr empty_view<T> empty{};
149
+ }
150
+
151
+ // [range.single], single view
152
+ template<copy_constructible T>
153
+ requires is_object_v<T>
154
+ class single_view;
155
+
156
+ namespace views { inline constexpr unspecified single = unspecified; }
157
+
158
+ // [range.iota], iota view
159
+ template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
160
+ requires weakly-equality-comparable-with<W, Bound>
161
+ class iota_view;
162
+
163
+ template<weakly_incrementable W, semiregular Bound>
164
+ inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
165
+
166
+ namespace views { inline constexpr unspecified iota = unspecified; }
167
+
168
+ // [range.istream], istream view
169
+ template<movable Val, class CharT, class Traits = char_traits<CharT>>
170
+ requires see below
171
+ class basic_istream_view;
172
+ template<class Val, class CharT, class Traits>
173
+ basic_istream_view<Val, CharT, Traits> istream_view(basic_istream<CharT, Traits>& s);
174
+
175
+ // [range.all], all view
176
+ namespace views {
177
+ inline constexpr unspecified all = unspecified;
178
+
179
+ template<viewable_range R>
180
+ using all_t = decltype(all(declval<R>()));
181
+ }
182
+
183
+ template<range R>
184
+ requires is_object_v<R>
185
+ class ref_view;
186
+
187
+ template<class T>
188
+ inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
189
+
190
+ // [range.filter], filter view
191
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
192
+ requires view<V> && is_object_v<Pred>
193
+ class filter_view;
194
+
195
+ namespace views { inline constexpr unspecified filter = unspecified; }
196
+
197
+ // [range.transform], transform view
198
+ template<input_range V, copy_constructible F>
199
+ requires view<V> && is_object_v<F> &&
200
+ regular_invocable<F&, range_reference_t<V>>
201
+ class transform_view;
202
+
203
+ namespace views { inline constexpr unspecified transform = unspecified; }
204
+
205
+ // [range.take], take view
206
+ template<view> class take_view;
207
+
208
+ namespace views { inline constexpr unspecified take = unspecified; }
209
+
210
+ // [range.take.while], take while view
211
+ template<view V, class Pred>
212
+ requires input_range<V> && is_object_v<Pred> &&
213
+ indirect_unary_predicate<const Pred, iterator_t<V>>
214
+ class take_while_view;
215
+
216
+ namespace views { inline constexpr unspecified take_while = unspecified; }
217
+
218
+ // [range.drop], drop view
219
+ template<view V>
220
+ class drop_view;
221
+
222
+ namespace views { inline constexpr unspecified drop = unspecified; }
223
+
224
+ // [range.drop.while], drop while view
225
+ template<view V, class Pred>
226
+ requires input_range<V> && is_object_v<Pred> &&
227
+ indirect_unary_predicate<const Pred, iterator_t<V>>
228
+ class drop_while_view;
229
+
230
+ namespace views { inline constexpr unspecified drop_while = unspecified; }
231
+
232
+ // [range.join], join view
233
+ template<input_range V>
234
+ requires view<V> && input_range<range_reference_t<V>> &&
235
+ (is_reference_v<range_reference_t<V>> ||
236
+ view<range_value_t<V>>)
237
+ class join_view;
238
+
239
+ namespace views { inline constexpr unspecified join = unspecified; }
240
+
241
+ // [range.split], split view
242
+ template<class R>
243
+ concept tiny-range = see below; // exposition only
244
+
245
+ template<input_range V, forward_range Pattern>
246
+ requires view<V> && view<Pattern> &&
247
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
248
+ (forward_range<V> || tiny-range<Pattern>)
249
+ class split_view;
250
+
251
+ namespace views { inline constexpr unspecified split = unspecified; }
252
+
253
+ // [range.counted], counted view
254
+ namespace views { inline constexpr unspecified counted = unspecified; }
255
+
256
+ // [range.common], common view
257
+ template<view V>
258
+ requires (!common_range<V> && copyable<iterator_t<V>>)
259
+ class common_view;
260
+
261
+ namespace views { inline constexpr unspecified common = unspecified; }
262
+
263
+ // [range.reverse], reverse view
264
+ template<view V>
265
+ requires bidirectional_range<V>
266
+ class reverse_view;
267
+
268
+ namespace views { inline constexpr unspecified reverse = unspecified; }
269
+
270
+ // [range.elements], elements view
271
+ template<input_range V, size_t N>
272
+ requires see below;
273
+ class elements_view;
274
+
275
+ template<class R>
276
+ using keys_view = elements_view<views::all_t<R>, 0>;
277
+ template<class R>
278
+ using values_view = elements_view<views::all_t<R>, 1>;
279
+
280
+ namespace views {
281
+ template<size_t N>
282
+ inline constexpr unspecified elements = unspecified ;
283
+ inline constexpr auto keys = elements<0>;
284
+ inline constexpr auto values = elements<1>;
285
+ }
286
+ }
287
+
288
+ namespace std {
289
+ namespace views = ranges::views;
290
+
291
+ template<class I, class S, ranges::subrange_kind K>
292
+ struct tuple_size<ranges::subrange<I, S, K>>
293
+ : integral_constant<size_t, 2> {};
294
+ template<class I, class S, ranges::subrange_kind K>
295
+ struct tuple_element<0, ranges::subrange<I, S, K>> {
296
+ using type = I;
297
+ };
298
+ template<class I, class S, ranges::subrange_kind K>
299
+ struct tuple_element<1, ranges::subrange<I, S, K>> {
300
+ using type = S;
301
+ };
302
+ template<class I, class S, ranges::subrange_kind K>
303
+ struct tuple_element<0, const ranges::subrange<I, S, K>> {
304
+ using type = I;
305
+ };
306
+ template<class I, class S, ranges::subrange_kind K>
307
+ struct tuple_element<1, const ranges::subrange<I, S, K>> {
308
+ using type = S;
309
+ };
310
+ }
311
+ ```
312
+
313
+ Within this clause, for an integer-like type `X`
314
+ [[iterator.concept.winc]], `make-unsigned-like-t<X>` denotes
315
+ `make_unsigned_t<X>` if `X` is an integer type; otherwise, it denotes a
316
+ corresponding unspecified unsigned-integer-like type of the same width
317
+ as `X`. For an expression `x` of type `X`, `to-unsigned-like(x)` is `x`
318
+ explicitly converted to `make-unsigned-like-t<X>`.
319
+
320
+ ## Range access <a id="range.access">[[range.access]]</a>
321
+
322
+ In addition to being available via inclusion of the `<ranges>` header,
323
+ the customization point objects in [[range.access]] are available when
324
+ `<iterator>` is included.
325
+
326
+ Within this subclause, the *reified object* of a subexpression `E`
327
+ denotes
328
+
329
+ - the same object as `E` if `E` is a glvalue, or
330
+ - the result of applying the temporary materialization conversion
331
+ [[conv.rval]] to `E` otherwise.
332
+
333
+ ### `ranges::begin` <a id="range.access.begin">[[range.access.begin]]</a>
334
+
335
+ The name `ranges::begin` denotes a customization point object
336
+ [[customization.point.object]].
337
+
338
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
339
+ denotes the reified object for `E`. Then:
340
+
341
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
342
+ `false`, `ranges::begin(E)` is ill-formed.
343
+ - Otherwise, if `T` is an array type [[basic.compound]] and
344
+ `remove_all_extents_t<T>` is an incomplete type, `ranges::begin(E)` is
345
+ ill-formed with no diagnostic required.
346
+ - Otherwise, if `T` is an array type, `ranges::begin(E)` is
347
+ expression-equivalent to `t + 0`.
348
+ - Otherwise, if `decay-copy(t.begin())` is a valid expression whose type
349
+ models `input_or_output_iterator`, `ranges::begin(E)` is
350
+ expression-equivalent to `decay-copy(t.begin())`.
351
+ - Otherwise, if `T` is a class or enumeration type and
352
+ `decay-copy(begin(t))` is a valid expression whose type models
353
+ `input_or_output_iterator` with overload resolution performed in a
354
+ context in which unqualified lookup for `begin` finds only the
355
+ declarations
356
+ ``` cpp
357
+ void begin(auto&) = delete;
358
+ void begin(const auto&) = delete;
359
+ ```
360
+
361
+ then `ranges::begin(E)` is expression-equivalent to
362
+ `decay-copy(begin(t))` with overload resolution performed in the above
363
+ context.
364
+ - Otherwise, `ranges::begin(E)` is ill-formed.
365
+
366
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
367
+ failure when `ranges::begin(E)` appears in the immediate context of a
368
+ template instantiation. — *end note*]
369
+
370
+ [*Note 2*: Whenever `ranges::begin(E)` is a valid expression, its type
371
+ models `input_or_output_iterator`. — *end note*]
372
+
373
+ ### `ranges::end` <a id="range.access.end">[[range.access.end]]</a>
374
+
375
+ The name `ranges::end` denotes a customization point object
376
+ [[customization.point.object]].
377
+
378
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
379
+ denotes the reified object for `E`. Then:
380
+
381
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
382
+ `false`, `ranges::end(E)` is ill-formed.
383
+ - Otherwise, if `T` is an array type [[basic.compound]] and
384
+ `remove_all_extents_t<T>` is an incomplete type, `ranges::end(E)` is
385
+ ill-formed with no diagnostic required.
386
+ - Otherwise, if `T` is an array of unknown bound, `ranges::end(E)` is
387
+ ill-formed.
388
+ - Otherwise, if `T` is an array, `ranges::end(E)` is
389
+ expression-equivalent to `t + extent_v<T>`.
390
+ - Otherwise, if `decay-copy(t.end())` is a valid expression whose type
391
+ models `sentinel_for<iterator_t<T>>` then `ranges::end(E)` is
392
+ expression-equivalent to `decay-copy(t.end())`.
393
+ - Otherwise, if `T` is a class or enumeration type and
394
+ `decay-copy(end(t))` is a valid expression whose type models
395
+ `sentinel_for<iterator_t<T>>` with overload resolution performed in a
396
+ context in which unqualified lookup for `end` finds only the
397
+ declarations
398
+ ``` cpp
399
+ void end(auto&) = delete;
400
+ void end(const auto&) = delete;
401
+ ```
402
+
403
+ then `ranges::end(E)` is expression-equivalent to `decay-copy(end(t))`
404
+ with overload resolution performed in the above context.
405
+ - Otherwise, `ranges::end(E)` is ill-formed.
406
+
407
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
408
+ failure when `ranges::end(E)` appears in the immediate context of a
409
+ template instantiation. — *end note*]
410
+
411
+ [*Note 2*: Whenever `ranges::end(E)` is a valid expression, the types
412
+ `S` and `I` of `ranges::end(E)` and `ranges::begin(E)` model
413
+ `sentinel_for<S, I>`. — *end note*]
414
+
415
+ ### `ranges::cbegin` <a id="range.access.cbegin">[[range.access.cbegin]]</a>
416
+
417
+ The name `ranges::cbegin` denotes a customization point object
418
+ [[customization.point.object]]. The expression `ranges::{}cbegin(E)` for
419
+ a subexpression `E` of type `T` is expression-equivalent to:
420
+
421
+ - `ranges::begin(static_cast<const T&>(E))` if `E` is an lvalue.
422
+ - Otherwise, `ranges::begin(static_cast<const T&&>(E))`.
423
+
424
+ [*Note 1*: Whenever `ranges::cbegin(E)` is a valid expression, its type
425
+ models `input_or_output_iterator`. — *end note*]
426
+
427
+ ### `ranges::cend` <a id="range.access.cend">[[range.access.cend]]</a>
428
+
429
+ The name `ranges::cend` denotes a customization point object
430
+ [[customization.point.object]]. The expression `ranges::cend(E)` for a
431
+ subexpression `E` of type `T` is expression-equivalent to:
432
+
433
+ - `ranges::end(static_cast<const T&>(E))` if `E` is an lvalue.
434
+ - Otherwise, `ranges::end(static_cast<const T&&>(E))`.
435
+
436
+ [*Note 1*: Whenever `ranges::cend(E)` is a valid expression, the types
437
+ `S` and `I` of `ranges::cend(E)` and `ranges::cbegin(E)` model
438
+ `sentinel_for<S, I>`. — *end note*]
439
+
440
+ ### `ranges::rbegin` <a id="range.access.rbegin">[[range.access.rbegin]]</a>
441
+
442
+ The name `ranges::rbegin` denotes a customization point object
443
+ [[customization.point.object]].
444
+
445
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
446
+ denotes the reified object for `E`. Then:
447
+
448
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
449
+ `false`, `ranges::rbegin(E)` is ill-formed.
450
+ - Otherwise, if `T` is an array type [[basic.compound]] and
451
+ `remove_all_extents_t<T>` is an incomplete type, `ranges::rbegin(E)`
452
+ is ill-formed with no diagnostic required.
453
+ - Otherwise, if `decay-copy(t.rbegin())` is a valid expression whose
454
+ type models `input_or_output_iterator`, `ranges::rbegin(E)` is
455
+ expression-equivalent to `decay-copy(t.rbegin())`.
456
+ - Otherwise, if `T` is a class or enumeration type and
457
+ `decay-copy(rbegin(t))` is a valid expression whose type models
458
+ `input_or_output_iterator` with overload resolution performed in a
459
+ context in which unqualified lookup for `rbegin` finds only the
460
+ declarations
461
+ ``` cpp
462
+ void rbegin(auto&) = delete;
463
+ void rbegin(const auto&) = delete;
464
+ ```
465
+
466
+ then `ranges::rbegin(E)` is expression-equivalent to
467
+ `decay-copy(rbegin(t))` with overload resolution performed in the
468
+ above context.
469
+ - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
470
+ expressions of the same type which models `bidirectional_iterator`
471
+ [[iterator.concept.bidir]], `ranges::rbegin(E)` is
472
+ expression-equivalent to `make_reverse_iterator(ranges::end(t))`.
473
+ - Otherwise, `ranges::rbegin(E)` is ill-formed.
474
+
475
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
476
+ failure when `ranges::rbegin(E)` appears in the immediate context of a
477
+ template instantiation. — *end note*]
478
+
479
+ [*Note 2*: Whenever `ranges::rbegin(E)` is a valid expression, its type
480
+ models `input_or_output_iterator`. — *end note*]
481
+
482
+ ### `ranges::rend` <a id="range.access.rend">[[range.access.rend]]</a>
483
+
484
+ The name `ranges::rend` denotes a customization point object
485
+ [[customization.point.object]].
486
+
487
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
488
+ denotes the reified object for `E`. Then:
489
+
490
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
491
+ `false`, `ranges::rend(E)` is ill-formed.
492
+ - Otherwise, if `T` is an array type [[basic.compound]] and
493
+ `remove_all_extents_t<T>` is an incomplete type, `ranges::rend(E)` is
494
+ ill-formed with no diagnostic required.
495
+ - Otherwise, if `decay-copy(t.rend())` is a valid expression whose type
496
+ models `sentinel_for<decltype(ranges::rbegin(E))>` then
497
+ `ranges::rend(E)` is expression-equivalent to
498
+ `decay-copy(t.rend({}))`.
499
+ - Otherwise, if `T` is a class or enumeration type and
500
+ `decay-copy(rend(t))` is a valid expression whose type models
501
+ `sentinel_for<decltype(ranges::rbegin(E))>` with overload resolution
502
+ performed in a context in which unqualified lookup for `rend` finds
503
+ only the declarations
504
+ ``` cpp
505
+ void rend(auto&) = delete;
506
+ void rend(const auto&) = delete;
507
+ ```
508
+
509
+ then `ranges::rend(E)` is expression-equivalent to
510
+ `decay-copy(rend(t))` with overload resolution performed in the above
511
+ context.
512
+ - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
513
+ expressions of the same type which models `bidirectional_iterator`
514
+ [[iterator.concept.bidir]], then `ranges::rend(E)` is
515
+ expression-equivalent to `make_reverse_iterator(ranges::begin(t))`.
516
+ - Otherwise, `ranges::rend(E)` is ill-formed.
517
+
518
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
519
+ failure when `ranges::rend(E)` appears in the immediate context of a
520
+ template instantiation. — *end note*]
521
+
522
+ [*Note 2*: Whenever `ranges::rend(E)` is a valid expression, the types
523
+ `S` and `I` of `ranges::rend(E)` and `ranges::rbegin(E)` model
524
+ `sentinel_for<S, I>`. — *end note*]
525
+
526
+ ### `ranges::crbegin` <a id="range.access.crbegin">[[range.access.crbegin]]</a>
527
+
528
+ The name `ranges::crbegin` denotes a customization point object
529
+ [[customization.point.object]]. The expression `ranges::{}crbegin(E)`
530
+ for a subexpression `E` of type `T` is expression-equivalent to:
531
+
532
+ - `ranges::{}rbegin(static_cast<const T&>(E))` if `E` is an lvalue.
533
+ - Otherwise, `ranges::rbegin(static_cast<const T&&>(E))`.
534
+
535
+ [*Note 1*: Whenever `ranges::crbegin(E)` is a valid expression, its
536
+ type models `input_or_output_iterator`. — *end note*]
537
+
538
+ ### `ranges::crend` <a id="range.access.crend">[[range.access.crend]]</a>
539
+
540
+ The name `ranges::crend` denotes a customization point object
541
+ [[customization.point.object]]. The expression `ranges::{}crend(E)` for
542
+ a subexpression `E` of type `T` is expression-equivalent to:
543
+
544
+ - `ranges::rend(static_cast<const T&>(E))` if `E` is an lvalue.
545
+ - Otherwise, `ranges::rend(static_cast<const T&&>(E))`.
546
+
547
+ [*Note 1*: Whenever `ranges::crend(E)` is a valid expression, the types
548
+ `S` and `I` of `ranges::crend(E)` and `ranges::crbegin(E)` model
549
+ `sentinel_for<S, I>`. — *end note*]
550
+
551
+ ### `ranges::size` <a id="range.prim.size">[[range.prim.size]]</a>
552
+
553
+ The name `ranges::size` denotes a customization point object
554
+ [[customization.point.object]].
555
+
556
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
557
+ denotes the reified object for `E`. Then:
558
+
559
+ - If `T` is an array of unknown bound [[dcl.array]], `ranges::size(E)`
560
+ is ill-formed.
561
+ - Otherwise, if `T` is an array type, `ranges::size(E)` is
562
+ expression-equivalent to `decay-copy(extent_v<T>)`.
563
+ - Otherwise, if `disable_sized_range<remove_cv_t<T>>` [[range.sized]] is
564
+ `false` and `decay-copy(t.size())` is a valid expression of
565
+ integer-like type [[iterator.concept.winc]], `ranges::size(E)` is
566
+ expression-equivalent to `decay-copy(t.size())`.
567
+ - Otherwise, if `T` is a class or enumeration type,
568
+ `disable_sized_range<remove_cv_t<T>>` is `false` and
569
+ `decay-copy(size(t))` is a valid expression of integer-like type with
570
+ overload resolution performed in a context in which unqualified lookup
571
+ for `size` finds only the declarations
572
+ ``` cpp
573
+ void size(auto&) = delete;
574
+ void size(const auto&) = delete;
575
+ ```
576
+
577
+ then `ranges::size(E)` is expression-equivalent to
578
+ `decay-copy(size(t))` with overload resolution performed in the above
579
+ context.
580
+ - Otherwise, if `to-unsigned-like(ranges::end(t) - ranges::begin(t))`
581
+ [[ranges.syn]] is a valid expression and the types `I` and `S` of
582
+ `ranges::begin(t)` and `ranges::end(t)` (respectively) model both
583
+ `sized_sentinel_for<S, I>` [[iterator.concept.sizedsentinel]] and
584
+ `forward_iterator<I>`, then `ranges::size(E)` is expression-equivalent
585
+ to `to-unsigned-like(ranges::end(t) - ranges::begin(t))`.
586
+ - Otherwise, `ranges::size(E)` is ill-formed.
587
+
588
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
589
+ failure when `ranges::size(E)` appears in the immediate context of a
590
+ template instantiation. — *end note*]
591
+
592
+ [*Note 2*: Whenever `ranges::size(E)` is a valid expression, its type
593
+ is integer-like. — *end note*]
594
+
595
+ ### `ranges::ssize` <a id="range.prim.ssize">[[range.prim.ssize]]</a>
596
+
597
+ The name `ranges::ssize` denotes a customization point object
598
+ [[customization.point.object]]. The expression `ranges::ssize({}E)` for
599
+ a subexpression `E` of type `T` is expression-equivalent to:
600
+
601
+ - If `range_difference_t<T>` has width less than `ptrdiff_t`,
602
+ `static_cast<ptrdiff_t>(ranges::{}size(E))`.
603
+ - Otherwise, `static_cast<range_difference_t<T>>(ranges::size(E))`.
604
+
605
+ ### `ranges::empty` <a id="range.prim.empty">[[range.prim.empty]]</a>
606
+
607
+ The name `ranges::empty` denotes a customization point object
608
+ [[customization.point.object]].
609
+
610
+ Given a subexpression `ranges::empty(E)` with type `T`, let `t` be an
611
+ lvalue that denotes the reified object for `E`. Then:
612
+
613
+ - If `T` is an array of unknown bound [[basic.compound]],
614
+ `ranges::empty(E)` is ill-formed.
615
+ - Otherwise, if `bool(t.empty())` is a valid expression,
616
+ `ranges::empty(E)` is expression-equivalent to `bool(t.empty())`.
617
+ - Otherwise, if `(ranges::size(t) == 0)` is a valid expression,
618
+ `ranges::empty(E)` is expression-equivalent to
619
+ `(ranges::size(t) == 0)`.
620
+ - Otherwise, if `bool(ranges::begin(t) == ranges::end(t))` is a valid
621
+ expression and the type of `ranges::begin(t)` models
622
+ `forward_iterator`, `ranges::empty(E)` is expression-equivalent to
623
+ `bool({}ranges::begin(t) == ranges::end(t))`.
624
+ - Otherwise, `ranges::empty(E)` is ill-formed.
625
+
626
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
627
+ failure when `ranges::empty(E)` appears in the immediate context of a
628
+ template instantiation. — *end note*]
629
+
630
+ [*Note 2*: Whenever `ranges::empty(E)` is a valid expression, it has
631
+ type `bool`. — *end note*]
632
+
633
+ ### `ranges::data` <a id="range.prim.data">[[range.prim.data]]</a>
634
+
635
+ The name `ranges::data` denotes a customization point object
636
+ [[customization.point.object]].
637
+
638
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
639
+ denotes the reified object for `E`. Then:
640
+
641
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
642
+ `false`, `ranges::data(E)` is ill-formed.
643
+ - Otherwise, if `T` is an array type [[basic.compound]] and
644
+ `remove_all_extents_t<T>` is an incomplete type, `ranges::data(E)` is
645
+ ill-formed with no diagnostic required.
646
+ - Otherwise, if `decay-copy(t.data())` is a valid expression of pointer
647
+ to object type, `ranges::data(E)` is expression-equivalent to
648
+ `decay-copy(t.data())`.
649
+ - Otherwise, if `ranges::begin(t)` is a valid expression whose type
650
+ models `contiguous_iterator`, `ranges::data(E)` is
651
+ expression-equivalent to `to_address(ranges::begin(E))`.
652
+ - Otherwise, `ranges::data(E)` is ill-formed.
653
+
654
+ [*Note 1*: Diagnosable ill-formed cases above result in substitution
655
+ failure when `ranges::data(E)` appears in the immediate context of a
656
+ template instantiation. — *end note*]
657
+
658
+ [*Note 2*: Whenever `ranges::data(E)` is a valid expression, it has
659
+ pointer to object type. — *end note*]
660
+
661
+ ### `ranges::cdata` <a id="range.prim.cdata">[[range.prim.cdata]]</a>
662
+
663
+ The name `ranges::cdata` denotes a customization point object
664
+ [[customization.point.object]]. The expression `ranges::{}cdata(E)` for
665
+ a subexpression `E` of type `T` is expression-equivalent to:
666
+
667
+ - `ranges::data(static_cast<const T&>(E))` if `E` is an lvalue.
668
+ - Otherwise, `ranges::data(static_cast<const T&&>(E))`.
669
+
670
+ [*Note 1*: Whenever `ranges::cdata(E)` is a valid expression, it has
671
+ pointer to object type. — *end note*]
672
+
673
+ ## Range requirements <a id="range.req">[[range.req]]</a>
674
+
675
+ ### General <a id="range.req.general">[[range.req.general]]</a>
676
+
677
+ Ranges are an abstraction that allow a C++ program to operate on
678
+ elements of data structures uniformly. Calling `ranges::begin` on a
679
+ range returns an object whose type models `input_or_output_iterator`
680
+ [[iterator.concept.iterator]]. Calling `ranges::end` on a range returns
681
+ an object whose type `S`, together with the type `I` of the object
682
+ returned by `ranges::begin`, models `sentinel_for<S, I>`. The library
683
+ formalizes the interfaces, semantics, and complexity of ranges to enable
684
+ algorithms and range adaptors that work efficiently on different types
685
+ of sequences.
686
+
687
+ The `range` concept requires that `ranges::begin` and `ranges::end`
688
+ return an iterator and a sentinel, respectively. The `sized_range`
689
+ concept refines `range` with the requirement that `ranges::size` be
690
+ amortized 𝑂(1). The `view` concept specifies requirements on a `range`
691
+ type with constant-time destruction and move operations.
692
+
693
+ Several refinements of `range` group requirements that arise frequently
694
+ in concepts and algorithms. Common ranges are ranges for which
695
+ `ranges::begin` and `ranges::end` return objects of the same type.
696
+ Random access ranges are ranges for which `ranges::begin` returns a type
697
+ that models `random_access_iterator` [[iterator.concept.random.access]].
698
+ (Contiguous, bidirectional, forward, input, and output ranges are
699
+ defined similarly.) Viewable ranges can be converted to views.
700
+
701
+ ### Ranges <a id="range.range">[[range.range]]</a>
702
+
703
+ The `range` concept defines the requirements of a type that allows
704
+ iteration over its elements by providing an iterator and sentinel that
705
+ denote the elements of the range.
706
+
707
+ ``` cpp
708
+ template<class T>
709
+ concept range =
710
+ requires(T& t) {
711
+ ranges::begin(t); // sometimes equality-preserving (see below)
712
+ ranges::end(t);
713
+ };
714
+ ```
715
+
716
+ The required expressions `ranges::begin(t)` and `ranges::end(t)` of the
717
+ `range` concept do not require implicit expression
718
+ variations [[concepts.equality]].
719
+
720
+ Given an expression `t` such that `decltype((t))` is `T&`, `T` models
721
+ `range` only if
722
+
723
+ - \[`ranges::begin(t)`, `ranges::end(t)`) denotes a
724
+ range [[iterator.requirements.general]],
725
+ - both `ranges::begin(t)` and `ranges::end(t)` are amortized constant
726
+ time and non-modifying, and
727
+ - if the type of `ranges::begin(t)` models `forward_iterator`,
728
+ `ranges::begin(t)` is equality-preserving.
729
+
730
+ [*Note 1*: Equality preservation of both `ranges::begin` and
731
+ `ranges::end` enables passing a `range` whose iterator type models
732
+ `forward_iterator` to multiple algorithms and making multiple passes
733
+ over the range by repeated calls to `ranges::begin` and `ranges::end`.
734
+ Since `ranges::begin` is not required to be equality-preserving when the
735
+ return type does not model `forward_iterator`, repeated calls might not
736
+ return equal values or might not be well-defined; `ranges::begin` should
737
+ be called at most once for such a range. — *end note*]
738
+
739
+ ``` cpp
740
+ template<class T>
741
+ concept borrowed_range =
742
+ range<T> &&
743
+ (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
744
+ ```
745
+
746
+ Given an expression `E` such that `decltype((E))` is `T`, `T` models
747
+ `borrowed_range` only if the validity of iterators obtained from the
748
+ object denoted by `E` is not tied to the lifetime of that object.
749
+
750
+ [*Note 2*: Since the validity of iterators is not tied to the lifetime
751
+ of an object whose type models `borrowed_range`, a function can accept
752
+ arguments of such a type by value and return iterators obtained from it
753
+ without danger of dangling. — *end note*]
754
+
755
+ ``` cpp
756
+ template<class>
757
+ inline constexpr bool enable_borrowed_range = false;
758
+ ```
759
+
760
+ *Remarks:* Pursuant to [[namespace.std]], users may specialize
761
+ `enable_borrowed_range` for cv-unqualified program-defined types. Such
762
+ specializations shall be usable in constant expressions [[expr.const]]
763
+ and have type `const bool`.
764
+
765
+ [*Example 1*:
766
+
767
+ Each specialization `S` of class template `subrange` [[range.subrange]]
768
+ models `borrowed_range` because
769
+
770
+ - `enable_borrowed_range<S>` is specialized to have the value `true`,
771
+ and
772
+ - `S`’s iterators do not have validity tied to the lifetime of an `S`
773
+ object because they are “borrowed” from some other range.
774
+
775
+ — *end example*]
776
+
777
+ ### Sized ranges <a id="range.sized">[[range.sized]]</a>
778
+
779
+ The `sized_range` concept refines `range` with the requirement that the
780
+ number of elements in the range can be determined in amortized constant
781
+ time using `ranges::size`.
782
+
783
+ ``` cpp
784
+ template<class T>
785
+ concept sized_range =
786
+ range<T> &&
787
+ requires(T& t) { ranges::size(t); };
788
+ ```
789
+
790
+ Given an lvalue `t` of type `remove_reference_t<T>`, `T` models
791
+ `sized_range` only if
792
+
793
+ - `ranges::size(t)` is amortized 𝑂(1), does not modify `t`, and is equal
794
+ to `ranges::distance(t)`, and
795
+ - if `iterator_t<T>` models `forward_iterator`, `ranges::size(t)` is
796
+ well-defined regardless of the evaluation of `ranges::begin(t)`.
797
+ \[*Note 1*: `ranges::size(t)` is otherwise not required to be
798
+ well-defined after evaluating `ranges::begin(t)`. For example,
799
+ `ranges::size(t)` might be well-defined for a `sized_range` whose
800
+ iterator type does not model `forward_iterator` only if evaluated
801
+ before the first call to `ranges::begin(t)`. — *end note*]
802
+
803
+ ``` cpp
804
+ template<class>
805
+ inline constexpr bool disable_sized_range = false;
806
+ ```
807
+
808
+ *Remarks:* Pursuant to [[namespace.std]], users may specialize
809
+ `disable_sized_range` for cv-unqualified program-defined types. Such
810
+ specializations shall be usable in constant expressions [[expr.const]]
811
+ and have type `const bool`.
812
+
813
+ [*Note 1*: `disable_sized_range` allows use of range types with the
814
+ library that satisfy but do not in fact model
815
+ `sized_range`. — *end note*]
816
+
817
+ ### Views <a id="range.view">[[range.view]]</a>
818
+
819
+ The `view` concept specifies the requirements of a `range` type that has
820
+ constant time move construction, move assignment, and destruction; that
821
+ is, the cost of these operations is independent of the number of
822
+ elements in the `view`.
823
+
824
+ ``` cpp
825
+ template<class T>
826
+ concept view =
827
+ range<T> && movable<T> && default_initializable<T> && enable_view<T>;
828
+ ```
829
+
830
+ `T` models `view` only if:
831
+
832
+ - `T` has 𝑂(1) move construction; and
833
+ - `T` has 𝑂(1) move assignment; and
834
+ - `T` has 𝑂(1) destruction; and
835
+ - `copy_constructible<T>` is `false`, or `T` has 𝑂(1) copy construction;
836
+ and
837
+ - `copyable<T>` is `false`, or `T` has 𝑂(1) copy assignment.
838
+
839
+ [*Example 1*:
840
+
841
+ Examples of `view`s are:
842
+
843
+ - A `range` type that wraps a pair of iterators.
844
+ - A `range` type that holds its elements by `shared_ptr` and shares
845
+ ownership with all its copies.
846
+ - A `range` type that generates its elements on demand.
847
+
848
+ Most containers [[containers]] are not views since destruction of the
849
+ container destroys the elements, which cannot be done in constant time.
850
+
851
+ — *end example*]
852
+
853
+ Since the difference between `range` and `view` is largely semantic, the
854
+ two are differentiated with the help of `enable_view`.
855
+
856
+ ``` cpp
857
+ template<class T>
858
+ inline constexpr bool enable_view = derived_from<T, view_base>;
859
+ ```
860
+
861
+ *Remarks:* Pursuant to [[namespace.std]], users may specialize
862
+ `enable_view` to `true` for cv-unqualified program-defined types which
863
+ model `view`, and `false` for types which do not. Such specializations
864
+ shall be usable in constant expressions [[expr.const]] and have type
865
+ `const bool`.
866
+
867
+ ### Other range refinements <a id="range.refinements">[[range.refinements]]</a>
868
+
869
+ The `output_range` concept specifies requirements of a `range` type for
870
+ which `ranges::begin` returns a model of `output_iterator`
871
+ [[iterator.concept.output]]. `input_range`, `forward_range`,
872
+ `bidirectional_range`, and `random_access_range` are defined similarly.
873
+
874
+ ``` cpp
875
+ template<class R, class T>
876
+ concept output_range =
877
+ range<R> && output_iterator<iterator_t<R>, T>;
878
+
879
+ template<class T>
880
+ concept input_range =
881
+ range<T> && input_iterator<iterator_t<T>>;
882
+
883
+ template<class T>
884
+ concept forward_range =
885
+ input_range<T> && forward_iterator<iterator_t<T>>;
886
+
887
+ template<class T>
888
+ concept bidirectional_range =
889
+ forward_range<T> && bidirectional_iterator<iterator_t<T>>;
890
+
891
+ template<class T>
892
+ concept random_access_range =
893
+ bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
894
+ ```
895
+
896
+ `contiguous_range` additionally requires that the `ranges::data`
897
+ customization point [[range.prim.data]] is usable with the range.
898
+
899
+ ``` cpp
900
+ template<class T>
901
+ concept contiguous_range =
902
+ random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
903
+ requires(T& t) {
904
+ { ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>;
905
+ };
906
+ ```
907
+
908
+ Given an expression `t` such that `decltype((t))` is `T&`, `T` models
909
+ `contiguous_range` only if
910
+ `to_address({}ranges::begin(t)) == ranges::data(t)` is `true`.
911
+
912
+ The `common_range` concept specifies requirements of a `range` type for
913
+ which `ranges::begin` and `ranges::end` return objects of the same type.
914
+
915
+ [*Example 1*: The standard containers [[containers]] model
916
+ `common_range`. — *end example*]
917
+
918
+ ``` cpp
919
+ template<class T>
920
+ concept common_range =
921
+ range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
922
+ ```
923
+
924
+ The `viewable_range` concept specifies the requirements of a `range`
925
+ type that can be converted to a `view` safely.
926
+
927
+ ``` cpp
928
+ template<class T>
929
+ concept viewable_range =
930
+ range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
931
+ ```
932
+
933
+ ## Range utilities <a id="range.utility">[[range.utility]]</a>
934
+
935
+ The components in this subclause are general utilities for representing
936
+ and manipulating ranges.
937
+
938
+ ### Helper concepts <a id="range.utility.helpers">[[range.utility.helpers]]</a>
939
+
940
+ Many of the types in subclause  [[range.utility]] are specified in terms
941
+ of the following exposition-only concepts:
942
+
943
+ ``` cpp
944
+ template<class R>
945
+ concept simple-view = // exposition only
946
+ view<R> && range<const R> &&
947
+ same_as<iterator_t<R>, iterator_t<const R>> &&
948
+ same_as<sentinel_t<R>, sentinel_t<const R>>;
949
+
950
+ template<class I>
951
+ concept has-arrow = // exposition only
952
+ input_iterator<I> && (is_pointer_v<I> || requires(I i) { i.operator->(); });
953
+
954
+ template<class T, class U>
955
+ concept not-same-as = // exposition only
956
+ !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
957
+ ```
958
+
959
+ ### View interface <a id="view.interface">[[view.interface]]</a>
960
+
961
+ The class template `view_interface` is a helper for defining `view`-like
962
+ types that offer a container-like interface. It is parameterized with
963
+ the type that is derived from it.
964
+
965
+ ``` cpp
966
+ namespace std::ranges {
967
+ template<class D>
968
+ requires is_class_v<D> && same_as<D, remove_cv_t<D>>
969
+ class view_interface : public view_base {
970
+ private:
971
+ constexpr D& derived() noexcept { // exposition only
972
+ return static_cast<D&>(*this);
973
+ }
974
+ constexpr const D& derived() const noexcept { // exposition only
975
+ return static_cast<const D&>(*this);
976
+ }
977
+ public:
978
+ constexpr bool empty() requires forward_range<D> {
979
+ return ranges::begin(derived()) == ranges::end(derived());
980
+ }
981
+ constexpr bool empty() const requires forward_range<const D> {
982
+ return ranges::begin(derived()) == ranges::end(derived());
983
+ }
984
+
985
+ constexpr explicit operator bool()
986
+ requires requires { ranges::empty(derived()); } {
987
+ return !ranges::empty(derived());
988
+ }
989
+ constexpr explicit operator bool() const
990
+ requires requires { ranges::empty(derived()); } {
991
+ return !ranges::empty(derived());
992
+ }
993
+
994
+ constexpr auto data() requires contiguous_iterator<iterator_t<D>> {
995
+ return to_address(ranges::begin(derived()));
996
+ }
997
+ constexpr auto data() const
998
+ requires range<const D> && contiguous_iterator<iterator_t<const D>> {
999
+ return to_address(ranges::begin(derived()));
1000
+ }
1001
+
1002
+ constexpr auto size() requires forward_range<D> &&
1003
+ sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
1004
+ return ranges::end(derived()) - ranges::begin(derived());
1005
+ }
1006
+ constexpr auto size() const requires forward_range<const D> &&
1007
+ sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
1008
+ return ranges::end(derived()) - ranges::begin(derived());
1009
+ }
1010
+
1011
+ constexpr decltype(auto) front() requires forward_range<D>;
1012
+ constexpr decltype(auto) front() const requires forward_range<const D>;
1013
+
1014
+ constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
1015
+ constexpr decltype(auto) back() const
1016
+ requires bidirectional_range<const D> && common_range<const D>;
1017
+
1018
+ template<random_access_range R = D>
1019
+ constexpr decltype(auto) operator[](range_difference_t<R> n) {
1020
+ return ranges::begin(derived())[n];
1021
+ }
1022
+ template<random_access_range R = const D>
1023
+ constexpr decltype(auto) operator[](range_difference_t<R> n) const {
1024
+ return ranges::begin(derived())[n];
1025
+ }
1026
+ };
1027
+ }
1028
+ ```
1029
+
1030
+ The template parameter `D` for `view_interface` may be an incomplete
1031
+ type. Before any member of the resulting specialization of
1032
+ `view_interface` other than special member functions is referenced, `D`
1033
+ shall be complete, and model both `derived_from<view_interface<D>>` and
1034
+ `view`.
1035
+
1036
+ #### Members <a id="view.interface.members">[[view.interface.members]]</a>
1037
+
1038
+ ``` cpp
1039
+ constexpr decltype(auto) front() requires forward_range<D>;
1040
+ constexpr decltype(auto) front() const requires forward_range<const D>;
1041
+ ```
1042
+
1043
+ *Preconditions:* `!empty()`.
1044
+
1045
+ *Effects:* Equivalent to: `return *ranges::begin(`*`derived`*`());`
1046
+
1047
+ ``` cpp
1048
+ constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
1049
+ constexpr decltype(auto) back() const
1050
+ requires bidirectional_range<const D> && common_range<const D>;
1051
+ ```
1052
+
1053
+ *Preconditions:* `!empty()`.
1054
+
1055
+ *Effects:* Equivalent to:
1056
+ `return *ranges::prev(ranges::end(`*`derived`*`()));`
1057
+
1058
+ ### Sub-ranges <a id="range.subrange">[[range.subrange]]</a>
1059
+
1060
+ The `subrange` class template combines together an iterator and a
1061
+ sentinel into a single object that models the `view` concept.
1062
+ Additionally, it models the `sized_range` concept when the final
1063
+ template parameter is `subrange_kind::sized`.
1064
+
1065
+ ``` cpp
1066
+ namespace std::ranges {
1067
+ template<class From, class To>
1068
+ concept convertible-to-non-slicing = // exposition only
1069
+ convertible_to<From, To> &&
1070
+ !(is_pointer_v<decay_t<From>> &&
1071
+ is_pointer_v<decay_t<To>> &&
1072
+ not-same-as<remove_pointer_t<decay_t<From>>, remove_pointer_t<decay_t<To>>>);
1073
+
1074
+ template<class T>
1075
+ concept pair-like = // exposition only
1076
+ !is_reference_v<T> && requires(T t) {
1077
+ typename tuple_size<T>::type; // ensures tuple_size<T> is complete
1078
+ requires derived_from<tuple_size<T>, integral_constant<size_t, 2>>;
1079
+ typename tuple_element_t<0, remove_const_t<T>>;
1080
+ typename tuple_element_t<1, remove_const_t<T>>;
1081
+ { get<0>(t) } -> convertible_to<const tuple_element_t<0, T>&>;
1082
+ { get<1>(t) } -> convertible_to<const tuple_element_t<1, T>&>;
1083
+ };
1084
+
1085
+ template<class T, class U, class V>
1086
+ concept pair-like-convertible-from = // exposition only
1087
+ !range<T> && pair-like<T> &&
1088
+ constructible_from<T, U, V> &&
1089
+ convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
1090
+ convertible_to<V, tuple_element_t<1, T>>;
1091
+
1092
+ template<class T>
1093
+ concept iterator-sentinel-pair = // exposition only
1094
+ !range<T> && pair-like<T> &&
1095
+ sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;
1096
+
1097
+ template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
1098
+ sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
1099
+ requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
1100
+ class subrange : public view_interface<subrange<I, S, K>> {
1101
+ private:
1102
+ static constexpr bool StoreSize = // exposition only
1103
+ K == subrange_kind::sized && !sized_sentinel_for<S, I>;
1104
+ I begin_ = I(); // exposition only
1105
+ S end_ = S(); // exposition only
1106
+ make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only
1107
+ // when StoreSize is true
1108
+ public:
1109
+ subrange() = default;
1110
+
1111
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
1112
+
1113
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
1114
+ make-unsigned-like-t<iter_difference_t<I>> n)
1115
+ requires (K == subrange_kind::sized);
1116
+
1117
+ template<not-same-as<subrange> R>
1118
+ requires borrowed_range<R> &&
1119
+ convertible-to-non-slicing<iterator_t<R>, I> &&
1120
+ convertible_to<sentinel_t<R>, S>
1121
+ constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1122
+
1123
+ template<borrowed_range R>
1124
+ requires convertible-to-non-slicing<iterator_t<R>, I> &&
1125
+ convertible_to<sentinel_t<R>, S>
1126
+ constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
1127
+ requires (K == subrange_kind::sized)
1128
+ : subrange{ranges::begin(r), ranges::end(r), n}
1129
+ {}
1130
+
1131
+ template<not-same-as<subrange> PairLike>
1132
+ requires pair-like-convertible-from<PairLike, const I&, const S&>
1133
+ constexpr operator PairLike() const;
1134
+
1135
+ constexpr I begin() const requires copyable<I>;
1136
+ [[nodiscard]] constexpr I begin() requires (!copyable<I>);
1137
+ constexpr S end() const;
1138
+
1139
+ constexpr bool empty() const;
1140
+ constexpr make-unsigned-like-t<iter_difference_t<I>> size() const
1141
+ requires (K == subrange_kind::sized);
1142
+
1143
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
1144
+ requires forward_iterator<I>;
1145
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
1146
+ [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
1147
+ requires bidirectional_iterator<I>;
1148
+ constexpr subrange& advance(iter_difference_t<I> n);
1149
+ };
1150
+
1151
+ template<input_or_output_iterator I, sentinel_for<I> S>
1152
+ subrange(I, S) -> subrange<I, S>;
1153
+
1154
+ template<input_or_output_iterator I, sentinel_for<I> S>
1155
+ subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
1156
+ subrange<I, S, subrange_kind::sized>;
1157
+
1158
+ template<iterator-sentinel-pair P>
1159
+ subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
1160
+
1161
+ template<iterator-sentinel-pair P>
1162
+ subrange(P, make-unsigned-like-t<iter_difference_t<tuple_element_t<0, P>>>) ->
1163
+ subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
1164
+
1165
+ template<borrowed_range R>
1166
+ subrange(R&&) ->
1167
+ subrange<iterator_t<R>, sentinel_t<R>,
1168
+ (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
1169
+ ? subrange_kind::sized : subrange_kind::unsized>;
1170
+
1171
+ template<borrowed_range R>
1172
+ subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) ->
1173
+ subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
1174
+
1175
+ template<size_t N, class I, class S, subrange_kind K>
1176
+ requires (N < 2)
1177
+ constexpr auto get(const subrange<I, S, K>& r);
1178
+
1179
+ template<size_t N, class I, class S, subrange_kind K>
1180
+ requires (N < 2)
1181
+ constexpr auto get(subrange<I, S, K>&& r);
1182
+ }
1183
+
1184
+ namespace std {
1185
+ using ranges::get;
1186
+ }
1187
+ ```
1188
+
1189
+ #### Constructors and conversions <a id="range.subrange.ctor">[[range.subrange.ctor]]</a>
1190
+
1191
+ ``` cpp
1192
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
1193
+ ```
1194
+
1195
+ *Preconditions:* \[`i`, `s`) is a valid range.
1196
+
1197
+ *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
1198
+ `s`.
1199
+
1200
+ ``` cpp
1201
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
1202
+ make-unsigned-like-t<iter_difference_t<I>> n)
1203
+ requires (K == subrange_kind::sized);
1204
+ ```
1205
+
1206
+ *Preconditions:* \[`i`, `s`) is a valid range, and
1207
+ `n == `*`to-unsigned-like`*`(ranges::distance(i, s))`.
1208
+
1209
+ *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
1210
+ `s`. If *StoreSize* is `true`, initializes *size\_* with `n`.
1211
+
1212
+ [*Note 1*: Accepting the length of the range and storing it to later
1213
+ return from `size()` enables `subrange` to model `sized_range` even when
1214
+ it stores an iterator and sentinel that do not model
1215
+ `sized_sentinel_for`. — *end note*]
1216
+
1217
+ ``` cpp
1218
+ template<not-same-as<subrange> R>
1219
+ requires borrowed_range<R> &&
1220
+ convertible-to-non-slicing<iterator_t<R>, I> &&
1221
+ convertible_to<sentinel_t<R>, S>
1222
+ constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1223
+ ```
1224
+
1225
+ *Effects:* Equivalent to:
1226
+
1227
+ - If *StoreSize* is `true`, `subrange{r, ranges::size(r)}`.
1228
+ - Otherwise, `subrange{ranges::begin(r), ranges::end(r)}`.
1229
+
1230
+ ``` cpp
1231
+ template<not-same-as<subrange> PairLike>
1232
+ requires pair-like-convertible-from<PairLike, const I&, const S&>
1233
+ constexpr operator PairLike() const;
1234
+ ```
1235
+
1236
+ *Effects:* Equivalent to: `return PairLike(`*`begin_`*`, `*`end_`*`);`
1237
+
1238
+ #### Accessors <a id="range.subrange.access">[[range.subrange.access]]</a>
1239
+
1240
+ ``` cpp
1241
+ constexpr I begin() const requires copyable<I>;
1242
+ ```
1243
+
1244
+ *Effects:* Equivalent to: `return `*`begin_`*`;`
1245
+
1246
+ ``` cpp
1247
+ [[nodiscard]] constexpr I begin() requires (!copyable<I>);
1248
+ ```
1249
+
1250
+ *Effects:* Equivalent to: `return std::move(`*`begin_`*`);`
1251
+
1252
+ ``` cpp
1253
+ constexpr S end() const;
1254
+ ```
1255
+
1256
+ *Effects:* Equivalent to: `return `*`end_`*`;`
1257
+
1258
+ ``` cpp
1259
+ constexpr bool empty() const;
1260
+ ```
1261
+
1262
+ *Effects:* Equivalent to: `return `*`begin_`*` == `*`end_`*`;`
1263
+
1264
+ ``` cpp
1265
+ constexpr make-unsigned-like-t<iter_difference_t<I>> size() const
1266
+ requires (K == subrange_kind::sized);
1267
+ ```
1268
+
1269
+ *Effects:*
1270
+
1271
+ - If *StoreSize* is `true`, equivalent to: `return `*`size_`*`;`
1272
+ - Otherwise, equivalent to:
1273
+ `return `*`to-unsigned-like`*`(`*`end_`*` - `*`begin_`*`);`
1274
+
1275
+ ``` cpp
1276
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
1277
+ requires forward_iterator<I>;
1278
+ ```
1279
+
1280
+ *Effects:* Equivalent to:
1281
+
1282
+ ``` cpp
1283
+ auto tmp = *this;
1284
+ tmp.advance(n);
1285
+ return tmp;
1286
+ ```
1287
+
1288
+ ``` cpp
1289
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
1290
+ ```
1291
+
1292
+ *Effects:* Equivalent to:
1293
+
1294
+ ``` cpp
1295
+ advance(n);
1296
+ return std::move(*this);
1297
+ ```
1298
+
1299
+ ``` cpp
1300
+ [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
1301
+ requires bidirectional_iterator<I>;
1302
+ ```
1303
+
1304
+ *Effects:* Equivalent to:
1305
+
1306
+ ``` cpp
1307
+ auto tmp = *this;
1308
+ tmp.advance(-n);
1309
+ return tmp;
1310
+ ```
1311
+
1312
+ ``` cpp
1313
+ constexpr subrange& advance(iter_difference_t<I> n);
1314
+ ```
1315
+
1316
+ *Effects:* Equivalent to:
1317
+
1318
+ - If *StoreSize* is `true`,
1319
+ ``` cpp
1320
+ auto d = n - ranges::advance(begin_, n, end_);
1321
+ if (d >= 0)
1322
+ size_ -= to-unsigned-like(d);
1323
+ else
1324
+ size_ += to-unsigned-like(-d);
1325
+ return *this;
1326
+ ```
1327
+ - Otherwise,
1328
+ ``` cpp
1329
+ ranges::advance(begin_, n, end_);
1330
+ return *this;
1331
+ ```
1332
+
1333
+ ``` cpp
1334
+ template<size_t N, class I, class S, subrange_kind K>
1335
+ requires (N < 2)
1336
+ constexpr auto get(const subrange<I, S, K>& r);
1337
+ template<size_t N, class I, class S, subrange_kind K>
1338
+ requires (N < 2)
1339
+ constexpr auto get(subrange<I, S, K>&& r);
1340
+ ```
1341
+
1342
+ *Effects:* Equivalent to:
1343
+
1344
+ ``` cpp
1345
+ if constexpr (N == 0)
1346
+ return r.begin();
1347
+ else
1348
+ return r.end();
1349
+ ```
1350
+
1351
+ ### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
1352
+
1353
+ The tag type `dangling` is used together with the template aliases
1354
+ `borrowed_iterator_t` and `borrowed_subrange_t` to indicate that an
1355
+ algorithm that typically returns an iterator into or subrange of a
1356
+ `range` argument does not return an iterator or subrange which could
1357
+ potentially reference a range whose lifetime has ended for a particular
1358
+ rvalue `range` argument which does not model `borrowed_range`
1359
+ [[range.range]].
1360
+
1361
+ ``` cpp
1362
+ namespace std::ranges {
1363
+ struct dangling {
1364
+ constexpr dangling() noexcept = default;
1365
+ template<class... Args>
1366
+ constexpr dangling(Args&&...) noexcept { }
1367
+ };
1368
+ }
1369
+ ```
1370
+
1371
+ [*Example 1*:
1372
+
1373
+ ``` cpp
1374
+ vector<int> f();
1375
+ auto result1 = ranges::find(f(), 42); // #1
1376
+ static_assert(same_as<decltype(result1), ranges::dangling>);
1377
+ auto vec = f();
1378
+ auto result2 = ranges::find(vec, 42); // #2
1379
+ static_assert(same_as<decltype(result2), vector<int>::iterator>);
1380
+ auto result3 = ranges::find(subrange{vec}, 42); // #3
1381
+ static_assert(same_as<decltype(result3), vector<int>::iterator>);
1382
+ ```
1383
+
1384
+ The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
1385
+ is an rvalue `vector`; the `vector` could potentially be destroyed
1386
+ before a returned iterator is dereferenced. However, the calls at \#2
1387
+ and \#3 both return iterators since the lvalue `vec` and specializations
1388
+ of `subrange` model `borrowed_range`.
1389
+
1390
+ — *end example*]
1391
+
1392
+ ## Range factories <a id="range.factories">[[range.factories]]</a>
1393
+
1394
+ This subclause defines *range factories*, which are utilities to create
1395
+ a `view`.
1396
+
1397
+ Range factories are declared in namespace `std::ranges::views`.
1398
+
1399
+ ### Empty view <a id="range.empty">[[range.empty]]</a>
1400
+
1401
+ #### Overview <a id="range.empty.overview">[[range.empty.overview]]</a>
1402
+
1403
+ `empty_view` produces a `view` of no elements of a particular type.
1404
+
1405
+ [*Example 1*:
1406
+
1407
+ ``` cpp
1408
+ empty_view<int> e;
1409
+ static_assert(ranges::empty(e));
1410
+ static_assert(0 == e.size());
1411
+ ```
1412
+
1413
+ — *end example*]
1414
+
1415
+ #### Class template `empty_view` <a id="range.empty.view">[[range.empty.view]]</a>
1416
+
1417
+ ``` cpp
1418
+ namespace std::ranges {
1419
+ template<class T>
1420
+ requires is_object_v<T>
1421
+ class empty_view : public view_interface<empty_view<T>> {
1422
+ public:
1423
+ static constexpr T* begin() noexcept { return nullptr; }
1424
+ static constexpr T* end() noexcept { return nullptr; }
1425
+ static constexpr T* data() noexcept { return nullptr; }
1426
+ static constexpr size_t size() noexcept { return 0; }
1427
+ static constexpr bool empty() noexcept { return true; }
1428
+ };
1429
+ }
1430
+ ```
1431
+
1432
+ ### Single view <a id="range.single">[[range.single]]</a>
1433
+
1434
+ #### Overview <a id="range.single.overview">[[range.single.overview]]</a>
1435
+
1436
+ `single_view` produces a `view` that contains exactly one element of a
1437
+ specified value.
1438
+
1439
+ The name `views::single` denotes a customization point object
1440
+ [[customization.point.object]]. Given a subexpression `E`, the
1441
+ expression `views::single(E)` is expression-equivalent to
1442
+ `single_view{E}`.
1443
+
1444
+ [*Example 1*:
1445
+
1446
+ ``` cpp
1447
+ single_view s{4};
1448
+ for (int i : s)
1449
+ cout << i; // prints 4
1450
+ ```
1451
+
1452
+ — *end example*]
1453
+
1454
+ #### Class template `single_view` <a id="range.single.view">[[range.single.view]]</a>
1455
+
1456
+ ``` cpp
1457
+ namespace std::ranges {
1458
+ template<copy_constructible T>
1459
+ requires is_object_v<T>
1460
+ class single_view : public view_interface<single_view<T>> {
1461
+ private:
1462
+ semiregular-box<T> value_; // exposition only{} (see [range.semi.wrap])
1463
+ public:
1464
+ single_view() = default;
1465
+ constexpr explicit single_view(const T& t);
1466
+ constexpr explicit single_view(T&& t);
1467
+ template<class... Args>
1468
+ requires constructible_from<T, Args...>
1469
+ constexpr single_view(in_place_t, Args&&... args);
1470
+
1471
+ constexpr T* begin() noexcept;
1472
+ constexpr const T* begin() const noexcept;
1473
+ constexpr T* end() noexcept;
1474
+ constexpr const T* end() const noexcept;
1475
+ static constexpr size_t size() noexcept;
1476
+ constexpr T* data() noexcept;
1477
+ constexpr const T* data() const noexcept;
1478
+ };
1479
+ }
1480
+ ```
1481
+
1482
+ ``` cpp
1483
+ constexpr explicit single_view(const T& t);
1484
+ ```
1485
+
1486
+ *Effects:* Initializes *value\_* with `t`.
1487
+
1488
+ ``` cpp
1489
+ constexpr explicit single_view(T&& t);
1490
+ ```
1491
+
1492
+ *Effects:* Initializes *value\_* with `std::move(t)`.
1493
+
1494
+ ``` cpp
1495
+ template<class... Args>
1496
+ constexpr single_view(in_place_t, Args&&... args);
1497
+ ```
1498
+
1499
+ *Effects:* Initializes *value\_* as if by
1500
+ *`value_`*`{in_place, std::forward<Args>(args)...}`.
1501
+
1502
+ ``` cpp
1503
+ constexpr T* begin() noexcept;
1504
+ constexpr const T* begin() const noexcept;
1505
+ ```
1506
+
1507
+ *Effects:* Equivalent to: `return data();`
1508
+
1509
+ ``` cpp
1510
+ constexpr T* end() noexcept;
1511
+ constexpr const T* end() const noexcept;
1512
+ ```
1513
+
1514
+ *Effects:* Equivalent to: `return data() + 1;`
1515
+
1516
+ ``` cpp
1517
+ static constexpr size_t size() noexcept;
1518
+ ```
1519
+
1520
+ *Effects:* Equivalent to: `return 1;`
1521
+
1522
+ ``` cpp
1523
+ constexpr T* data() noexcept;
1524
+ constexpr const T* data() const noexcept;
1525
+ ```
1526
+
1527
+ *Effects:* Equivalent to: `return `*`value_`*`.operator->();`
1528
+
1529
+ ### Iota view <a id="range.iota">[[range.iota]]</a>
1530
+
1531
+ #### Overview <a id="range.iota.overview">[[range.iota.overview]]</a>
1532
+
1533
+ `iota_view` generates a sequence of elements by repeatedly incrementing
1534
+ an initial value.
1535
+
1536
+ The name `views::iota` denotes a customization point object
1537
+ [[customization.point.object]]. Given subexpressions `E` and `F`, the
1538
+ expressions `views::iota(E)` and `views::iota(E, F)` are
1539
+ expression-equivalent to `iota_view{E}` and `iota_view{E, F}`,
1540
+ respectively.
1541
+
1542
+ [*Example 1*:
1543
+
1544
+ ``` cpp
1545
+ for (int i : iota_view{1, 10})
1546
+ cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
1547
+ ```
1548
+
1549
+ — *end example*]
1550
+
1551
+ #### Class template `iota_view` <a id="range.iota.view">[[range.iota.view]]</a>
1552
+
1553
+ ``` cpp
1554
+ namespace std::ranges {
1555
+ template<class I>
1556
+ concept decrementable = // exposition only
1557
+ see below;
1558
+ template<class I>
1559
+ concept advanceable = // exposition only
1560
+ see below;
1561
+
1562
+ template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
1563
+ requires weakly-equality-comparable-with<W, Bound> && semiregular<W>
1564
+ class iota_view : public view_interface<iota_view<W, Bound>> {
1565
+ private:
1566
+ // [range.iota.iterator], class iota_view::iterator
1567
+ struct iterator; // exposition only
1568
+ // [range.iota.sentinel], class iota_view::sentinel
1569
+ struct sentinel; // exposition only
1570
+ W value_ = W(); // exposition only
1571
+ Bound bound_ = Bound(); // exposition only
1572
+ public:
1573
+ iota_view() = default;
1574
+ constexpr explicit iota_view(W value);
1575
+ constexpr iota_view(type_identity_t<W> value,
1576
+ type_identity_t<Bound> bound);
1577
+ constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}
1578
+
1579
+ constexpr iterator begin() const;
1580
+ constexpr auto end() const;
1581
+ constexpr iterator end() const requires same_as<W, Bound>;
1582
+
1583
+ constexpr auto size() const requires see below;
1584
+ };
1585
+
1586
+ template<class W, class Bound>
1587
+ requires (!is-integer-like<W> || !is-integer-like<Bound> ||
1588
+ (is-signed-integer-like<W> == is-signed-integer-like<Bound>))
1589
+ iota_view(W, Bound) -> iota_view<W, Bound>;
1590
+ }
1591
+ ```
1592
+
1593
+ Let `IOTA-DIFF-T(W)` be defined as follows:
1594
+
1595
+ - If `W` is not an integral type, or if it is an integral type and
1596
+ `sizeof(iter_difference_t<W>)` is greater than `sizeof(W)`, then
1597
+ `IOTA-DIFF-T(W)` denotes `iter_difference_t<W>`.
1598
+ - Otherwise, `IOTA-DIFF-T(W)` is a signed integer type of width greater
1599
+ than the width of `W` if such a type exists.
1600
+ - Otherwise, `IOTA-DIFF-T(W)` is an unspecified signed-integer-like type
1601
+ [[iterator.concept.winc]] of width not less than the width of `W`.
1602
+ \[*Note 1*: It is unspecified whether this type satisfies
1603
+ `weakly_incrementable`. — *end note*]
1604
+
1605
+ The exposition-only *decrementable* concept is equivalent to:
1606
+
1607
+ ``` cpp
1608
+ template<class I>
1609
+ concept decrementable =
1610
+ incrementable<I> && requires(I i) {
1611
+ { --i } -> same_as<I&>;
1612
+ { i-- } -> same_as<I>;
1613
+ };
1614
+ ```
1615
+
1616
+ When an object is in the domain of both pre- and post-decrement, the
1617
+ object is said to be *decrementable*.
1618
+
1619
+ Let `a` and `b` be equal objects of type `I`. `I` models `decrementable`
1620
+ only if
1621
+
1622
+ - If `a` and `b` are decrementable, then the following are all true:
1623
+ - `addressof(–a) == addressof(a)`
1624
+ - `bool(a– == b)`
1625
+ - `bool(((void)a–, a) == –b)`
1626
+ - `bool(++(–a) == b)`.
1627
+ - If `a` and `b` are incrementable, then `bool(–(++a) == b)`.
1628
+
1629
+ The exposition-only *advanceable* concept is equivalent to:
1630
+
1631
+ ``` cpp
1632
+ template<class I>
1633
+ concept advanceable =
1634
+ decrementable<I> && totally_ordered<I> &&
1635
+ requires(I i, const I j, const IOTA-DIFF-T(I) n) {
1636
+ { i += n } -> same_as<I&>;
1637
+ { i -= n } -> same_as<I&>;
1638
+ I(j + n);
1639
+ I(n + j);
1640
+ I(j - n);
1641
+ { j - j } -> convertible_to<IOTA-DIFF-T(I)>;
1642
+ };
1643
+ ```
1644
+
1645
+ Let `D` be `IOTA-DIFF-T(I)`. Let `a` and `b` be objects of type `I` such
1646
+ that `b` is reachable from `a` after `n` applications of `++a`, for some
1647
+ value `n` of type `D`. `I` models `advanceable` only if
1648
+
1649
+ - `(a += n)` is equal to `b`.
1650
+ - `addressof(a += n)` is equal to `addressof(a)`.
1651
+ - `I(a + n)` is equal to `(a += n)`.
1652
+ - For any two positive values `x` and `y` of type `D`, if
1653
+ `I(a + D(x + y))` is well-defined, then `I(a + D(x + y))` is equal to
1654
+ `I(I(a + x) + y)`.
1655
+ - `I(a + D(0))` is equal to `a`.
1656
+ - If `I(a + D(n - 1))` is well-defined, then `I(a + n)` is equal to
1657
+ `[](I c) { return ++c; }(I(a + D(n - 1)))`.
1658
+ - `(b += -n)` is equal to `a`.
1659
+ - `(b -= n)` is equal to `a`.
1660
+ - `addressof(b -= n)` is equal to `addressof(b)`.
1661
+ - `I(b - n)` is equal to `(b -= n)`.
1662
+ - `D(b - a)` is equal to `n`.
1663
+ - `D(a - b)` is equal to `D(-n)`.
1664
+ - `bool(a <= b)` is `true`.
1665
+
1666
+ ``` cpp
1667
+ constexpr explicit iota_view(W value);
1668
+ ```
1669
+
1670
+ *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `Bound()`
1671
+ is reachable from `value`.
1672
+
1673
+ *Effects:* Initializes *value\_* with `value`.
1674
+
1675
+ ``` cpp
1676
+ constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
1677
+ ```
1678
+
1679
+ *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `bound` is
1680
+ reachable from `value`. When `W` and `Bound` model
1681
+ `totally_ordered_with`, then `bool(value <= bound)` is `true`.
1682
+
1683
+ *Effects:* Initializes *value\_* with `value` and *bound\_* with
1684
+ `bound`.
1685
+
1686
+ ``` cpp
1687
+ constexpr iterator begin() const;
1688
+ ```
1689
+
1690
+ *Effects:* Equivalent to: `return iterator{`*`value_`*`};`
1691
+
1692
+ ``` cpp
1693
+ constexpr auto end() const;
1694
+ ```
1695
+
1696
+ *Effects:* Equivalent to:
1697
+
1698
+ ``` cpp
1699
+ if constexpr (same_as<Bound, unreachable_sentinel_t>)
1700
+ return unreachable_sentinel;
1701
+ else
1702
+ return sentinel{bound_};
1703
+ ```
1704
+
1705
+ ``` cpp
1706
+ constexpr iterator end() const requires same_as<W, Bound>;
1707
+ ```
1708
+
1709
+ *Effects:* Equivalent to: `return iterator{bound_};`
1710
+
1711
+ ``` cpp
1712
+ constexpr auto size() const requires see below;
1713
+ ```
1714
+
1715
+ *Effects:* Equivalent to:
1716
+
1717
+ ``` cpp
1718
+ if constexpr (is-integer-like<W> && is-integer-like<Bound>)
1719
+ return (value_ < 0)
1720
+ ? ((bound_ < 0)
1721
+ ? to-unsigned-like(-value_) - to-unsigned-like(-bound_)
1722
+ : to-unsigned-like(bound_) + to-unsigned-like(-value_))
1723
+ : to-unsigned-like(bound_) - to-unsigned-like(value_);
1724
+ else
1725
+ return to-unsigned-like(bound_ - value_);
1726
+ ```
1727
+
1728
+ *Remarks:* The expression in the *requires-clause* is equivalent to
1729
+
1730
+ ``` cpp
1731
+ (same_as<W, Bound> && advanceable<W>) || (integral<W> && integral<Bound>) ||
1732
+ sized_sentinel_for<Bound, W>
1733
+ ```
1734
+
1735
+ #### Class `iota_view::iterator` <a id="range.iota.iterator">[[range.iota.iterator]]</a>
1736
+
1737
+ ``` cpp
1738
+ namespace std::ranges {
1739
+ template<weakly_incrementable W, semiregular Bound>
1740
+ requires weakly-equality-comparable-with<W, Bound>
1741
+ struct iota_view<W, Bound>::iterator {
1742
+ private:
1743
+ W value_ = W(); // exposition only
1744
+ public:
1745
+ using iterator_concept = see below;
1746
+ using iterator_category = input_iterator_tag;
1747
+ using value_type = W;
1748
+ using difference_type = IOTA-DIFF-T(W);
1749
+
1750
+ iterator() = default;
1751
+ constexpr explicit iterator(W value);
1752
+
1753
+ constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
1754
+
1755
+ constexpr iterator& operator++();
1756
+ constexpr void operator++(int);
1757
+ constexpr iterator operator++(int) requires incrementable<W>;
1758
+
1759
+ constexpr iterator& operator--() requires decrementable<W>;
1760
+ constexpr iterator operator--(int) requires decrementable<W>;
1761
+
1762
+ constexpr iterator& operator+=(difference_type n)
1763
+ requires advanceable<W>;
1764
+ constexpr iterator& operator-=(difference_type n)
1765
+ requires advanceable<W>;
1766
+ constexpr W operator[](difference_type n) const
1767
+ requires advanceable<W>;
1768
+
1769
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
1770
+ requires equality_comparable<W>;
1771
+
1772
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
1773
+ requires totally_ordered<W>;
1774
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
1775
+ requires totally_ordered<W>;
1776
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
1777
+ requires totally_ordered<W>;
1778
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
1779
+ requires totally_ordered<W>;
1780
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
1781
+ requires totally_ordered<W> && three_way_comparable<W>;
1782
+
1783
+ friend constexpr iterator operator+(iterator i, difference_type n)
1784
+ requires advanceable<W>;
1785
+ friend constexpr iterator operator+(difference_type n, iterator i)
1786
+ requires advanceable<W>;
1787
+
1788
+ friend constexpr iterator operator-(iterator i, difference_type n)
1789
+ requires advanceable<W>;
1790
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
1791
+ requires advanceable<W>;
1792
+ };
1793
+ }
1794
+ ```
1795
+
1796
+ `iterator::iterator_concept` is defined as follows:
1797
+
1798
+ - If `W` models `advanceable`, then `iterator_concept` is
1799
+ `random_access_iterator_tag`.
1800
+ - Otherwise, if `W` models `decrementable`, then `iterator_concept` is
1801
+ `bidirectional_iterator_tag`.
1802
+ - Otherwise, if `W` models `incrementable`, then `iterator_concept` is
1803
+ `forward_iterator_tag`.
1804
+ - Otherwise, `iterator_concept` is `input_iterator_tag`.
1805
+
1806
+ [*Note 1*: Overloads for `iter_move` and `iter_swap` are omitted
1807
+ intentionally. — *end note*]
1808
+
1809
+ ``` cpp
1810
+ constexpr explicit iterator(W value);
1811
+ ```
1812
+
1813
+ *Effects:* Initializes *value\_* with `value`.
1814
+
1815
+ ``` cpp
1816
+ constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
1817
+ ```
1818
+
1819
+ *Effects:* Equivalent to: `return `*`value_`*`;`
1820
+
1821
+ [*Note 1*: The `noexcept` clause is needed by the default `iter_move`
1822
+ implementation. — *end note*]
1823
+
1824
+ ``` cpp
1825
+ constexpr iterator& operator++();
1826
+ ```
1827
+
1828
+ *Effects:* Equivalent to:
1829
+
1830
+ ``` cpp
1831
+ ++value_;
1832
+ return *this;
1833
+ ```
1834
+
1835
+ ``` cpp
1836
+ constexpr void operator++(int);
1837
+ ```
1838
+
1839
+ *Effects:* Equivalent to `++*this`.
1840
+
1841
+ ``` cpp
1842
+ constexpr iterator operator++(int) requires incrementable<W>;
1843
+ ```
1844
+
1845
+ *Effects:* Equivalent to:
1846
+
1847
+ ``` cpp
1848
+ auto tmp = *this;
1849
+ ++*this;
1850
+ return tmp;
1851
+ ```
1852
+
1853
+ ``` cpp
1854
+ constexpr iterator& operator--() requires decrementable<W>;
1855
+ ```
1856
+
1857
+ *Effects:* Equivalent to:
1858
+
1859
+ ``` cpp
1860
+ --value_;
1861
+ return *this;
1862
+ ```
1863
+
1864
+ ``` cpp
1865
+ constexpr iterator operator--(int) requires decrementable<W>;
1866
+ ```
1867
+
1868
+ *Effects:* Equivalent to:
1869
+
1870
+ ``` cpp
1871
+ auto tmp = *this;
1872
+ --*this;
1873
+ return tmp;
1874
+ ```
1875
+
1876
+ ``` cpp
1877
+ constexpr iterator& operator+=(difference_type n)
1878
+ requires advanceable<W>;
1879
+ ```
1880
+
1881
+ *Effects:* Equivalent to:
1882
+
1883
+ ``` cpp
1884
+ if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) {
1885
+ if (n >= difference_type(0))
1886
+ value_ += static_cast<W>(n);
1887
+ else
1888
+ value_ -= static_cast<W>(-n);
1889
+ } else {
1890
+ value_ += n;
1891
+ }
1892
+ return *this;
1893
+ ```
1894
+
1895
+ ``` cpp
1896
+ constexpr iterator& operator-=(difference_type n)
1897
+ requires advanceable<W>;
1898
+ ```
1899
+
1900
+ *Effects:* Equivalent to:
1901
+
1902
+ ``` cpp
1903
+ if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) {
1904
+ if (n >= difference_type(0))
1905
+ value_ -= static_cast<W>(n);
1906
+ else
1907
+ value_ += static_cast<W>(-n);
1908
+ } else {
1909
+ value_ -= n;
1910
+ }
1911
+ return *this;
1912
+ ```
1913
+
1914
+ ``` cpp
1915
+ constexpr W operator[](difference_type n) const
1916
+ requires advanceable<W>;
1917
+ ```
1918
+
1919
+ *Effects:* Equivalent to: `return W(`*`value_`*` + n);`
1920
+
1921
+ ``` cpp
1922
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
1923
+ requires equality_comparable<W>;
1924
+ ```
1925
+
1926
+ *Effects:* Equivalent to: `return x.`*`value_`*` == y.`*`value_`*`;`
1927
+
1928
+ ``` cpp
1929
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
1930
+ requires totally_ordered<W>;
1931
+ ```
1932
+
1933
+ *Effects:* Equivalent to: `return x.`*`value_`*` < y.`*`value_`*`;`
1934
+
1935
+ ``` cpp
1936
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
1937
+ requires totally_ordered<W>;
1938
+ ```
1939
+
1940
+ *Effects:* Equivalent to: `return y < x;`
1941
+
1942
+ ``` cpp
1943
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
1944
+ requires totally_ordered<W>;
1945
+ ```
1946
+
1947
+ *Effects:* Equivalent to: `return !(y < x);`
1948
+
1949
+ ``` cpp
1950
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
1951
+ requires totally_ordered<W>;
1952
+ ```
1953
+
1954
+ *Effects:* Equivalent to: `return !(x < y);`
1955
+
1956
+ ``` cpp
1957
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
1958
+ requires totally_ordered<W> && three_way_comparable<W>;
1959
+ ```
1960
+
1961
+ *Effects:* Equivalent to: `return x.`*`value_`*` <=> y.`*`value_`*`;`
1962
+
1963
+ ``` cpp
1964
+ friend constexpr iterator operator+(iterator i, difference_type n)
1965
+ requires advanceable<W>;
1966
+ ```
1967
+
1968
+ *Effects:* Equivalent to: `return i += n;`
1969
+
1970
+ ``` cpp
1971
+ friend constexpr iterator operator+(difference_type n, iterator i)
1972
+ requires advanceable<W>;
1973
+ ```
1974
+
1975
+ *Effects:* Equivalent to: `return i + n;`
1976
+
1977
+ ``` cpp
1978
+ friend constexpr iterator operator-(iterator i, difference_type n)
1979
+ requires advanceable<W>;
1980
+ ```
1981
+
1982
+ *Effects:* Equivalent to: `return i -= n;`
1983
+
1984
+ ``` cpp
1985
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
1986
+ requires advanceable<W>;
1987
+ ```
1988
+
1989
+ *Effects:* Equivalent to:
1990
+
1991
+ ``` cpp
1992
+ using D = difference_type;
1993
+ if constexpr (is-integer-like<W>) {
1994
+ if constexpr (is-signed-integer-like<W>)
1995
+ return D(D(x.value_) - D(y.value_));
1996
+ else
1997
+ return (y.value_ > x.value_)
1998
+ ? D(-D(y.value_ - x.value_))
1999
+ : D(x.value_ - y.value_);
2000
+ } else {
2001
+ return x.value_ - y.value_;
2002
+ }
2003
+ ```
2004
+
2005
+ #### Class `iota_view::sentinel` <a id="range.iota.sentinel">[[range.iota.sentinel]]</a>
2006
+
2007
+ ``` cpp
2008
+ namespace std::ranges {
2009
+ template<weakly_incrementable W, semiregular Bound>
2010
+ requires weakly-equality-comparable-with<W, Bound>
2011
+ struct iota_view<W, Bound>::sentinel {
2012
+ private:
2013
+ Bound bound_ = Bound(); // exposition only
2014
+ public:
2015
+ sentinel() = default;
2016
+ constexpr explicit sentinel(Bound bound);
2017
+
2018
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
2019
+
2020
+ friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y)
2021
+ requires sized_sentinel_for<Bound, W>;
2022
+ friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y)
2023
+ requires sized_sentinel_for<Bound, W>;
2024
+ };
2025
+ }
2026
+ ```
2027
+
2028
+ ``` cpp
2029
+ constexpr explicit sentinel(Bound bound);
2030
+ ```
2031
+
2032
+ *Effects:* Initializes *bound\_* with `bound`.
2033
+
2034
+ ``` cpp
2035
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
2036
+ ```
2037
+
2038
+ *Effects:* Equivalent to: `return x.`*`value_`*` == y.`*`bound_`*`;`
2039
+
2040
+ ``` cpp
2041
+ friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y)
2042
+ requires sized_sentinel_for<Bound, W>;
2043
+ ```
2044
+
2045
+ *Effects:* Equivalent to: `return x.`*`value_`*` - y.`*`bound_`*`;`
2046
+
2047
+ ``` cpp
2048
+ friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y)
2049
+ requires sized_sentinel_for<Bound, W>;
2050
+ ```
2051
+
2052
+ *Effects:* Equivalent to: `return -(y - x);`
2053
+
2054
+ ### Istream view <a id="range.istream">[[range.istream]]</a>
2055
+
2056
+ #### Overview <a id="range.istream.overview">[[range.istream.overview]]</a>
2057
+
2058
+ `basic_istream_view` models `input_range` and reads (using `operator>>`)
2059
+ successive elements from its corresponding input stream.
2060
+
2061
+ [*Example 1*:
2062
+
2063
+ ``` cpp
2064
+ auto ints = istringstream{"0 1 2 3 4"};
2065
+ ranges::copy(istream_view<int>(ints), ostream_iterator<int>{cout, "-"});
2066
+ // prints 0-1-2-3-4-
2067
+ ```
2068
+
2069
+ — *end example*]
2070
+
2071
+ #### Class template `basic_istream_view` <a id="range.istream.view">[[range.istream.view]]</a>
2072
+
2073
+ ``` cpp
2074
+ namespace std::ranges {
2075
+ template<class Val, class CharT, class Traits>
2076
+ concept stream-extractable = // exposition only
2077
+ requires(basic_istream<CharT, Traits>& is, Val& t) {
2078
+ is >> t;
2079
+ };
2080
+
2081
+ template<movable Val, class CharT, class Traits>
2082
+ requires default_initializable<Val> &&
2083
+ stream-extractable<Val, CharT, Traits>
2084
+ class basic_istream_view : public view_interface<basic_istream_view<Val, CharT, Traits>> {
2085
+ public:
2086
+ basic_istream_view() = default;
2087
+ constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
2088
+
2089
+ constexpr auto begin()
2090
+ {
2091
+ if (stream_) {
2092
+ *stream_ >> object_;
2093
+ }
2094
+ return iterator{*this};
2095
+ }
2096
+
2097
+ constexpr default_sentinel_t end() const noexcept;
2098
+
2099
+ private:
2100
+ struct iterator; // exposition only
2101
+ basic_istream<CharT, Traits>* stream_ = nullptr; // exposition only
2102
+ Val object_ = Val(); // exposition only
2103
+ };
2104
+ }
2105
+ ```
2106
+
2107
+ ``` cpp
2108
+ constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
2109
+ ```
2110
+
2111
+ *Effects:* Initializes *stream\_* with `addressof(stream)`.
2112
+
2113
+ ``` cpp
2114
+ constexpr default_sentinel_t end() const noexcept;
2115
+ ```
2116
+
2117
+ *Effects:* Equivalent to: `return default_sentinel;`
2118
+
2119
+ ``` cpp
2120
+ template<class Val, class CharT, class Traits>
2121
+ basic_istream_view<Val, CharT, Traits> istream_view(basic_istream<CharT, Traits>& s);
2122
+ ```
2123
+
2124
+ *Effects:* Equivalent to:
2125
+ `return basic_istream_view<Val, CharT, Traits>{s};`
2126
+
2127
+ #### Class template `basic_istream_view::iterator` <a id="range.istream.iterator">[[range.istream.iterator]]</a>
2128
+
2129
+ ``` cpp
2130
+ namespace std::ranges {
2131
+ template<movable Val, class CharT, class Traits>
2132
+ requires default_initializable<Val> &&
2133
+ stream-extractable<Val, CharT, Traits>
2134
+ class basic_istream_view<Val, CharT, Traits>::iterator { // exposition only
2135
+ public:
2136
+ using iterator_concept = input_iterator_tag;
2137
+ using difference_type = ptrdiff_t;
2138
+ using value_type = Val;
2139
+
2140
+ iterator() = default;
2141
+ constexpr explicit iterator(basic_istream_view& parent) noexcept;
2142
+
2143
+ iterator(const iterator&) = delete;
2144
+ iterator(iterator&&) = default;
2145
+
2146
+ iterator& operator=(const iterator&) = delete;
2147
+ iterator& operator=(iterator&&) = default;
2148
+
2149
+ iterator& operator++();
2150
+ void operator++(int);
2151
+
2152
+ Val& operator*() const;
2153
+
2154
+ friend bool operator==(const iterator& x, default_sentinel_t);
2155
+
2156
+ private:
2157
+ basic_istream_view* parent_ = nullptr; // exposition only
2158
+ };
2159
+ }
2160
+ ```
2161
+
2162
+ ``` cpp
2163
+ constexpr explicit iterator(basic_istream_view& parent) noexcept;
2164
+ ```
2165
+
2166
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
2167
+
2168
+ ``` cpp
2169
+ iterator& operator++();
2170
+ ```
2171
+
2172
+ *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2173
+
2174
+ *Effects:* Equivalent to:
2175
+
2176
+ ``` cpp
2177
+ *parent_->stream_>> parent_->object_;
2178
+ return *this;
2179
+ ```
2180
+
2181
+ ``` cpp
2182
+ void operator++(int);
2183
+ ```
2184
+
2185
+ *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2186
+
2187
+ *Effects:* Equivalent to `++*this`.
2188
+
2189
+ ``` cpp
2190
+ Val& operator*() const;
2191
+ ```
2192
+
2193
+ *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2194
+
2195
+ *Effects:* Equivalent to: `return `*`parent_`*`->`*`object_`*`;`
2196
+
2197
+ ``` cpp
2198
+ friend bool operator==(const iterator& x, default_sentinel_t);
2199
+ ```
2200
+
2201
+ *Effects:* Equivalent to:
2202
+ `return x.`*`parent_`*` == nullptr || !*x.`*`parent_`*`->`*`stream_`*`;`
2203
+
2204
+ ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
2205
+
2206
+ This subclause defines *range adaptors*, which are utilities that
2207
+ transform a `range` into a `view` with custom behaviors. These adaptors
2208
+ can be chained to create pipelines of range transformations that
2209
+ evaluate lazily as the resulting view is iterated.
2210
+
2211
+ Range adaptors are declared in namespace `std::ranges::views`.
2212
+
2213
+ The bitwise operator is overloaded for the purpose of creating adaptor
2214
+ chain pipelines. The adaptors also support function call syntax with
2215
+ equivalent semantics.
2216
+
2217
+ [*Example 1*:
2218
+
2219
+ ``` cpp
2220
+ vector<int> ints{0,1,2,3,4,5};
2221
+ auto even = [](int i){ return 0 == i % 2; };
2222
+ auto square = [](int i) { return i * i; };
2223
+ for (int i : ints | views::filter(even) | views::transform(square)) {
2224
+ cout << i << ' '; // prints: 0 4 16
2225
+ }
2226
+ assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
2227
+ ```
2228
+
2229
+ — *end example*]
2230
+
2231
+ ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
2232
+
2233
+ A *range adaptor closure object* is a unary function object that accepts
2234
+ a `viewable_range` argument and returns a `view`. For a range adaptor
2235
+ closure object `C` and an expression `R` such that `decltype((R))`
2236
+ models `viewable_range`, the following expressions are equivalent and
2237
+ yield a `view`:
2238
+
2239
+ ``` cpp
2240
+ C(R)
2241
+ R | C
2242
+ ```
2243
+
2244
+ Given an additional range adaptor closure object `D`, the expression
2245
+ `C | D` is well-formed and produces another range adaptor closure object
2246
+ such that the following two expressions are equivalent:
2247
+
2248
+ ``` cpp
2249
+ R | C | D
2250
+ R | (C | D)
2251
+ ```
2252
+
2253
+ A *range adaptor object* is a customization point object
2254
+ [[customization.point.object]] that accepts a `viewable_range` as its
2255
+ first argument and returns a `view`.
2256
+
2257
+ If a range adaptor object accepts only one argument, then it is a range
2258
+ adaptor closure object.
2259
+
2260
+ If a range adaptor object accepts more than one argument, then the
2261
+ following expressions are equivalent:
2262
+
2263
+ ``` cpp
2264
+ adaptor(range, args...)
2265
+ adaptor(args...)(range)
2266
+ range | adaptor(args...)
2267
+ ```
2268
+
2269
+ In this case, `adaptor(args...)` is a range adaptor closure object.
2270
+
2271
+ ### Semiregular wrapper <a id="range.semi.wrap">[[range.semi.wrap]]</a>
2272
+
2273
+ Many types in this subclause are specified in terms of an
2274
+ exposition-only class template *`semiregular-box`*. `semiregular-box<T>`
2275
+ behaves exactly like `optional<T>` with the following differences:
2276
+
2277
+ - `semiregular-box<T>` constrains its type parameter `T` with
2278
+ `copy_constructible<T> && is_object_v<T>`.
2279
+ - If `T` models `default_initializable`, the default constructor of
2280
+ `semiregular-box<T>` is equivalent to:
2281
+ ``` cpp
2282
+ constexpr semiregular-box() noexcept(is_nothrow_default_constructible_v<T>)
2283
+ : semiregular-box{in_place}
2284
+ { }
2285
+ ```
2286
+ - If `assignable_from<T&, const T&>` is not modeled, the copy assignment
2287
+ operator is equivalent to:
2288
+ ``` cpp
2289
+ semiregular-box& operator=(const semiregular-box& that)
2290
+ noexcept(is_nothrow_copy_constructible_v<T>)
2291
+ {
2292
+ if (that) emplace(*that);
2293
+ else reset();
2294
+ return *this;
2295
+ }
2296
+ ```
2297
+ - If `assignable_from<T&, T>` is not modeled, the move assignment
2298
+ operator is equivalent to:
2299
+ ``` cpp
2300
+ semiregular-box& operator=(semiregular-box&& that)
2301
+ noexcept(is_nothrow_move_constructible_v<T>)
2302
+ {
2303
+ if (that) emplace(std::move(*that));
2304
+ else reset();
2305
+ return *this;
2306
+ }
2307
+ ```
2308
+
2309
+ ### All view <a id="range.all">[[range.all]]</a>
2310
+
2311
+ `views::all` returns a `view` that includes all elements of its `range`
2312
+ argument.
2313
+
2314
+ The name `views::all` denotes a range adaptor object
2315
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
2316
+ `views::all(E)` is expression-equivalent to:
2317
+
2318
+ - `decay-copy(E)` if the decayed type of `E` models `view`.
2319
+ - Otherwise, `ref_view{E}` if that expression is well-formed.
2320
+ - Otherwise, `subrange{E}`.
2321
+
2322
+ #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
2323
+
2324
+ `ref_view` is a `view` of the elements of some other `range`.
2325
+
2326
+ ``` cpp
2327
+ namespace std::ranges {
2328
+ template<range R>
2329
+ requires is_object_v<R>
2330
+ class ref_view : public view_interface<ref_view<R>> {
2331
+ private:
2332
+ R* r_ = nullptr; // exposition only
2333
+ public:
2334
+ constexpr ref_view() noexcept = default;
2335
+
2336
+ template<not-same-as<ref_view> T>
2337
+ requires see below
2338
+ constexpr ref_view(T&& t);
2339
+
2340
+ constexpr R& base() const { return *r_; }
2341
+
2342
+ constexpr iterator_t<R> begin() const { return ranges::begin(*r_); }
2343
+ constexpr sentinel_t<R> end() const { return ranges::end(*r_); }
2344
+
2345
+ constexpr bool empty() const
2346
+ requires requires { ranges::empty(*r_); }
2347
+ { return ranges::empty(*r_); }
2348
+
2349
+ constexpr auto size() const requires sized_range<R>
2350
+ { return ranges::size(*r_); }
2351
+
2352
+ constexpr auto data() const requires contiguous_range<R>
2353
+ { return ranges::data(*r_); }
2354
+ };
2355
+ template<class R>
2356
+ ref_view(R&) -> ref_view<R>;
2357
+ }
2358
+ ```
2359
+
2360
+ ``` cpp
2361
+ template<not-same-as<ref_view> T>
2362
+ requires see below
2363
+ constexpr ref_view(T&& t);
2364
+ ```
2365
+
2366
+ *Remarks:* Let *`FUN`* denote the exposition-only functions
2367
+
2368
+ ``` cpp
2369
+ void FUN(R&);
2370
+ void FUN(R&&) = delete;
2371
+ ```
2372
+
2373
+ The expression in the *requires-clause* is equivalent to
2374
+
2375
+ ``` cpp
2376
+ convertible_to<T, R&> && requires { FUN(declval<T>()); }
2377
+ ```
2378
+
2379
+ *Effects:* Initializes *r\_* with
2380
+ `addressof(static_cast<R&>(std::forward<T>(t)))`.
2381
+
2382
+ ### Filter view <a id="range.filter">[[range.filter]]</a>
2383
+
2384
+ #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
2385
+
2386
+ `filter_view` presents a `view` of the elements of an underlying
2387
+ sequence that satisfy a predicate.
2388
+
2389
+ The name `views::filter` denotes a range adaptor object
2390
+ [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
2391
+ expression `views::filter(E, P)` is expression-equivalent to
2392
+ `filter_view{E, P}`.
2393
+
2394
+ [*Example 1*:
2395
+
2396
+ ``` cpp
2397
+ vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
2398
+ filter_view evens{is, [](int i) { return 0 == i % 2; }};
2399
+ for (int i : evens)
2400
+ cout << i << ' '; // prints: 0 2 4 6
2401
+ ```
2402
+
2403
+ — *end example*]
2404
+
2405
+ #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
2406
+
2407
+ ``` cpp
2408
+ namespace std::ranges {
2409
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
2410
+ requires view<V> && is_object_v<Pred>
2411
+ class filter_view : public view_interface<filter_view<V, Pred>> {
2412
+ private:
2413
+ V base_ = V(); // exposition only
2414
+ semiregular-box<Pred> pred_; // exposition only
2415
+
2416
+ // [range.filter.iterator], class filter_view::iterator
2417
+ class iterator; // exposition only
2418
+ // [range.filter.sentinel], class filter_view::sentinel
2419
+ class sentinel; // exposition only
2420
+
2421
+ public:
2422
+ filter_view() = default;
2423
+ constexpr filter_view(V base, Pred pred);
2424
+
2425
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
2426
+ constexpr V base() && { return std::move(base_); }
2427
+
2428
+ constexpr const Pred& pred() const;
2429
+
2430
+ constexpr iterator begin();
2431
+ constexpr auto end() {
2432
+ if constexpr (common_range<V>)
2433
+ return iterator{*this, ranges::end(base_)};
2434
+ else
2435
+ return sentinel{*this};
2436
+ }
2437
+ };
2438
+
2439
+ template<class R, class Pred>
2440
+ filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
2441
+ }
2442
+ ```
2443
+
2444
+ ``` cpp
2445
+ constexpr filter_view(V base, Pred pred);
2446
+ ```
2447
+
2448
+ *Effects:* Initializes *base\_* with `std::move(base)` and initializes
2449
+ *pred\_* with `std::move(pred)`.
2450
+
2451
+ ``` cpp
2452
+ constexpr const Pred& pred() const;
2453
+ ```
2454
+
2455
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
2456
+
2457
+ ``` cpp
2458
+ constexpr iterator begin();
2459
+ ```
2460
+
2461
+ *Preconditions:* `pred_.has_value()`.
2462
+
2463
+ *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
2464
+
2465
+ *Remarks:* In order to provide the amortized constant time complexity
2466
+ required by the `range` concept when `filter_view` models
2467
+ `forward_range`, this function caches the result within the
2468
+ `filter_view` for use on subsequent calls.
2469
+
2470
+ #### Class `filter_view::iterator` <a id="range.filter.iterator">[[range.filter.iterator]]</a>
2471
+
2472
+ ``` cpp
2473
+ namespace std::ranges {
2474
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
2475
+ requires view<V> && is_object_v<Pred>
2476
+ class filter_view<V, Pred>::iterator {
2477
+ private:
2478
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only
2479
+ filter_view* parent_ = nullptr; // exposition only
2480
+ public:
2481
+ using iterator_concept = see below;
2482
+ using iterator_category = see below;
2483
+ using value_type = range_value_t<V>;
2484
+ using difference_type = range_difference_t<V>;
2485
+
2486
+ iterator() = default;
2487
+ constexpr iterator(filter_view& parent, iterator_t<V> current);
2488
+
2489
+ constexpr iterator_t<V> base() const &
2490
+ requires copyable<iterator_t<V>>;
2491
+ constexpr iterator_t<V> base() &&;
2492
+ constexpr range_reference_t<V> operator*() const;
2493
+ constexpr iterator_t<V> operator->() const
2494
+ requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
2495
+
2496
+ constexpr iterator& operator++();
2497
+ constexpr void operator++(int);
2498
+ constexpr iterator operator++(int) requires forward_range<V>;
2499
+
2500
+ constexpr iterator& operator--() requires bidirectional_range<V>;
2501
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
2502
+
2503
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2504
+ requires equality_comparable<iterator_t<V>>;
2505
+
2506
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
2507
+ noexcept(noexcept(ranges::iter_move(i.current_)));
2508
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
2509
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
2510
+ requires indirectly_swappable<iterator_t<V>>;
2511
+ };
2512
+ }
2513
+ ```
2514
+
2515
+ Modification of the element a `filter_view::iterator` denotes is
2516
+ permitted, but results in undefined behavior if the resulting value does
2517
+ not satisfy the filter predicate.
2518
+
2519
+ `iterator::iterator_concept` is defined as follows:
2520
+
2521
+ - If `V` models `bidirectional_range`, then `iterator_concept` denotes
2522
+ `bidirectional_iterator_tag`.
2523
+ - Otherwise, if `V` models `forward_range`, then `iterator_concept`
2524
+ denotes `forward_iterator_tag`.
2525
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2526
+
2527
+ `iterator::iterator_category` is defined as follows:
2528
+
2529
+ - Let `C` denote the type
2530
+ `iterator_traits<iterator_t<V>>::iterator_category`.
2531
+ - If `C` models `derived_from<bidirectional_iterator_tag>`, then
2532
+ `iterator_category` denotes `bidirectional_iterator_tag`.
2533
+ - Otherwise, if `C` models `derived_from<forward_iterator_tag>`, then
2534
+ `iterator_category` denotes `forward_iterator_tag`.
2535
+ - Otherwise, `iterator_category` denotes `C`.
2536
+
2537
+ ``` cpp
2538
+ constexpr iterator(filter_view& parent, iterator_t<V> current);
2539
+ ```
2540
+
2541
+ *Effects:* Initializes *current\_* with `std::move(current)` and
2542
+ *parent\_* with `addressof(parent)`.
2543
+
2544
+ ``` cpp
2545
+ constexpr iterator_t<V> base() const &
2546
+ requires copyable<iterator_t<V>>;
2547
+ ```
2548
+
2549
+ *Effects:* Equivalent to: `return `*`current_`*`;`
2550
+
2551
+ ``` cpp
2552
+ constexpr iterator_t<V> base() &&;
2553
+ ```
2554
+
2555
+ *Effects:* Equivalent to: `return std::move(current_);`
2556
+
2557
+ ``` cpp
2558
+ constexpr range_reference_t<V> operator*() const;
2559
+ ```
2560
+
2561
+ *Effects:* Equivalent to: `return *`*`current_`*`;`
2562
+
2563
+ ``` cpp
2564
+ constexpr iterator_t<V> operator->() const
2565
+ requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
2566
+ ```
2567
+
2568
+ *Effects:* Equivalent to: `return `*`current_`*`;`
2569
+
2570
+ ``` cpp
2571
+ constexpr iterator& operator++();
2572
+ ```
2573
+
2574
+ *Effects:* Equivalent to:
2575
+
2576
+ ``` cpp
2577
+ current_ = ranges::find_if(std::move(++current_), ranges::end(parent_->base_),
2578
+ ref(*parent_->pred_));
2579
+ return *this;
2580
+ ```
2581
+
2582
+ ``` cpp
2583
+ constexpr void operator++(int);
2584
+ ```
2585
+
2586
+ *Effects:* Equivalent to `++*this`.
2587
+
2588
+ ``` cpp
2589
+ constexpr iterator operator++(int) requires forward_range<V>;
2590
+ ```
2591
+
2592
+ *Effects:* Equivalent to:
2593
+
2594
+ ``` cpp
2595
+ auto tmp = *this;
2596
+ ++*this;
2597
+ return tmp;
2598
+ ```
2599
+
2600
+ ``` cpp
2601
+ constexpr iterator& operator--() requires bidirectional_range<V>;
2602
+ ```
2603
+
2604
+ *Effects:* Equivalent to:
2605
+
2606
+ ``` cpp
2607
+ do
2608
+ --current_;
2609
+ while (!invoke(*parent_->pred_, *current_));
2610
+ return *this;
2611
+ ```
2612
+
2613
+ ``` cpp
2614
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
2615
+ ```
2616
+
2617
+ *Effects:* Equivalent to:
2618
+
2619
+ ``` cpp
2620
+ auto tmp = *this;
2621
+ --*this;
2622
+ return tmp;
2623
+ ```
2624
+
2625
+ ``` cpp
2626
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2627
+ requires equality_comparable<iterator_t<V>>;
2628
+ ```
2629
+
2630
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
2631
+
2632
+ ``` cpp
2633
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
2634
+ noexcept(noexcept(ranges::iter_move(i.current_)));
2635
+ ```
2636
+
2637
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
2638
+
2639
+ ``` cpp
2640
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
2641
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
2642
+ requires indirectly_swappable<iterator_t<V>>;
2643
+ ```
2644
+
2645
+ *Effects:* Equivalent to
2646
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
2647
+
2648
+ #### Class `filter_view::sentinel` <a id="range.filter.sentinel">[[range.filter.sentinel]]</a>
2649
+
2650
+ ``` cpp
2651
+ namespace std::ranges {
2652
+ template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
2653
+ requires view<V> && is_object_v<Pred>
2654
+ class filter_view<V, Pred>::sentinel {
2655
+ private:
2656
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
2657
+ public:
2658
+ sentinel() = default;
2659
+ constexpr explicit sentinel(filter_view& parent);
2660
+
2661
+ constexpr sentinel_t<V> base() const;
2662
+
2663
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
2664
+ };
2665
+ }
2666
+ ```
2667
+
2668
+ ``` cpp
2669
+ constexpr explicit sentinel(filter_view& parent);
2670
+ ```
2671
+
2672
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
2673
+
2674
+ ``` cpp
2675
+ constexpr sentinel_t<V> base() const;
2676
+ ```
2677
+
2678
+ *Effects:* Equivalent to: `return `*`end_`*`;`
2679
+
2680
+ ``` cpp
2681
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
2682
+ ```
2683
+
2684
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
2685
+
2686
+ ### Transform view <a id="range.transform">[[range.transform]]</a>
2687
+
2688
+ #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
2689
+
2690
+ `transform_view` presents a `view` of an underlying sequence after
2691
+ applying a transformation function to each element.
2692
+
2693
+ The name `views::transform` denotes a range adaptor object
2694
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
2695
+ expression `views::transform(E, F)` is expression-equivalent to
2696
+ `transform_view{E, F}`.
2697
+
2698
+ [*Example 1*:
2699
+
2700
+ ``` cpp
2701
+ vector<int> is{ 0, 1, 2, 3, 4 };
2702
+ transform_view squares{is, [](int i) { return i * i; }};
2703
+ for (int i : squares)
2704
+ cout << i << ' '; // prints: 0 1 4 9 16
2705
+ ```
2706
+
2707
+ — *end example*]
2708
+
2709
+ #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
2710
+
2711
+ ``` cpp
2712
+ namespace std::ranges {
2713
+ template<input_range V, copy_constructible F>
2714
+ requires view<V> && is_object_v<F> &&
2715
+ regular_invocable<F&, range_reference_t<V>> &&
2716
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
2717
+ class transform_view : public view_interface<transform_view<V, F>> {
2718
+ private:
2719
+ // [range.transform.iterator], class template transform_view::iterator
2720
+ template<bool> struct iterator; // exposition only
2721
+ // [range.transform.sentinel], class template transform_view::sentinel
2722
+ template<bool> struct sentinel; // exposition only
2723
+
2724
+ V base_ = V(); // exposition only
2725
+ semiregular-box<F> fun_; // exposition only
2726
+
2727
+ public:
2728
+ transform_view() = default;
2729
+ constexpr transform_view(V base, F fun);
2730
+
2731
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
2732
+ constexpr V base() && { return std::move(base_); }
2733
+
2734
+ constexpr iterator<false> begin();
2735
+ constexpr iterator<true> begin() const
2736
+ requires range<const V> &&
2737
+ regular_invocable<const F&, range_reference_t<const V>>;
2738
+
2739
+ constexpr sentinel<false> end();
2740
+ constexpr iterator<false> end() requires common_range<V>;
2741
+ constexpr sentinel<true> end() const
2742
+ requires range<const V> &&
2743
+ regular_invocable<const F&, range_reference_t<const V>>;
2744
+ constexpr iterator<true> end() const
2745
+ requires common_range<const V> &&
2746
+ regular_invocable<const F&, range_reference_t<const V>>;
2747
+
2748
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
2749
+ constexpr auto size() const requires sized_range<const V>
2750
+ { return ranges::size(base_); }
2751
+ };
2752
+
2753
+ template<class R, class F>
2754
+ transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
2755
+ }
2756
+ ```
2757
+
2758
+ ``` cpp
2759
+ constexpr transform_view(V base, F fun);
2760
+ ```
2761
+
2762
+ *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
2763
+ `std::move(fun)`.
2764
+
2765
+ ``` cpp
2766
+ constexpr iterator<false> begin();
2767
+ ```
2768
+
2769
+ *Effects:* Equivalent to:
2770
+
2771
+ ``` cpp
2772
+ return iterator<false>{*this, ranges::begin(base_)};
2773
+ ```
2774
+
2775
+ ``` cpp
2776
+ constexpr iterator<true> begin() const
2777
+ requires range<const V> &&
2778
+ regular_invocable<const F&, range_reference_t<const V>>;
2779
+ ```
2780
+
2781
+ *Effects:* Equivalent to:
2782
+
2783
+ ``` cpp
2784
+ return iterator<true>{*this, ranges::begin(base_)};
2785
+ ```
2786
+
2787
+ ``` cpp
2788
+ constexpr sentinel<false> end();
2789
+ ```
2790
+
2791
+ *Effects:* Equivalent to:
2792
+
2793
+ ``` cpp
2794
+ return sentinel<false>{ranges::end(base_)};
2795
+ ```
2796
+
2797
+ ``` cpp
2798
+ constexpr iterator<false> end() requires common_range<V>;
2799
+ ```
2800
+
2801
+ *Effects:* Equivalent to:
2802
+
2803
+ ``` cpp
2804
+ return iterator<false>{*this, ranges::end(base_)};
2805
+ ```
2806
+
2807
+ ``` cpp
2808
+ constexpr sentinel<true> end() const
2809
+ requires range<const V> &&
2810
+ regular_invocable<const F&, range_reference_t<const V>>;
2811
+ ```
2812
+
2813
+ *Effects:* Equivalent to:
2814
+
2815
+ ``` cpp
2816
+ return sentinel<true>{ranges::end(base_)};
2817
+ ```
2818
+
2819
+ ``` cpp
2820
+ constexpr iterator<true> end() const
2821
+ requires common_range<const V> &&
2822
+ regular_invocable<const F&, range_reference_t<const V>>;
2823
+ ```
2824
+
2825
+ *Effects:* Equivalent to:
2826
+
2827
+ ``` cpp
2828
+ return iterator<true>{*this, ranges::end(base_)};
2829
+ ```
2830
+
2831
+ #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
2832
+
2833
+ ``` cpp
2834
+ namespace std::ranges {
2835
+ template<input_range V, copy_constructible F>
2836
+ requires view<V> && is_object_v<F> &&
2837
+ regular_invocable<F&, range_reference_t<V>> &&
2838
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
2839
+ template<bool Const>
2840
+ class transform_view<V, F>::iterator {
2841
+ private:
2842
+ using Parent = // exposition only
2843
+ conditional_t<Const, const transform_view, transform_view>;
2844
+ using Base = // exposition only
2845
+ conditional_t<Const, const V, V>;
2846
+ iterator_t<Base> current_ = // exposition only
2847
+ iterator_t<Base>();
2848
+ Parent* parent_ = nullptr; // exposition only
2849
+ public:
2850
+ using iterator_concept = see below;
2851
+ using iterator_category = see below;
2852
+ using value_type =
2853
+ remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
2854
+ using difference_type = range_difference_t<Base>;
2855
+
2856
+ iterator() = default;
2857
+ constexpr iterator(Parent& parent, iterator_t<Base> current);
2858
+ constexpr iterator(iterator<!Const> i)
2859
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2860
+
2861
+ constexpr iterator_t<Base> base() const &
2862
+ requires copyable<iterator_t<Base>>;
2863
+ constexpr iterator_t<Base> base() &&;
2864
+ constexpr decltype(auto) operator*() const
2865
+ { return invoke(*parent_->fun_, *current_); }
2866
+
2867
+ constexpr iterator& operator++();
2868
+ constexpr void operator++(int);
2869
+ constexpr iterator operator++(int) requires forward_range<Base>;
2870
+
2871
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
2872
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
2873
+
2874
+ constexpr iterator& operator+=(difference_type n)
2875
+ requires random_access_range<Base>;
2876
+ constexpr iterator& operator-=(difference_type n)
2877
+ requires random_access_range<Base>;
2878
+ constexpr decltype(auto) operator[](difference_type n) const
2879
+ requires random_access_range<Base>
2880
+ { return invoke(*parent_->fun_, current_[n]); }
2881
+
2882
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2883
+ requires equality_comparable<iterator_t<Base>>;
2884
+
2885
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
2886
+ requires random_access_range<Base>;
2887
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
2888
+ requires random_access_range<Base>;
2889
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
2890
+ requires random_access_range<Base>;
2891
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
2892
+ requires random_access_range<Base>;
2893
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
2894
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
2895
+
2896
+ friend constexpr iterator operator+(iterator i, difference_type n)
2897
+ requires random_access_range<Base>;
2898
+ friend constexpr iterator operator+(difference_type n, iterator i)
2899
+ requires random_access_range<Base>;
2900
+
2901
+ friend constexpr iterator operator-(iterator i, difference_type n)
2902
+ requires random_access_range<Base>;
2903
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
2904
+ requires random_access_range<Base>;
2905
+
2906
+ friend constexpr decltype(auto) iter_move(const iterator& i)
2907
+ noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
2908
+ {
2909
+ if constexpr (is_lvalue_reference_v<decltype(*i)>)
2910
+ return std::move(*i);
2911
+ else
2912
+ return *i;
2913
+ }
2914
+
2915
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
2916
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
2917
+ requires indirectly_swappable<iterator_t<Base>>;
2918
+ };
2919
+ }
2920
+ ```
2921
+
2922
+ `iterator::iterator_concept` is defined as follows:
2923
+
2924
+ - If `V` models `random_access_range`, then `iterator_concept` denotes
2925
+ `random_access_iterator_tag`.
2926
+ - Otherwise, if `V` models `bidirectional_range`, then
2927
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
2928
+ - Otherwise, if `V` models `forward_range`, then `iterator_concept`
2929
+ denotes `forward_iterator_tag`.
2930
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2931
+
2932
+ `iterator::iterator_category` is defined as follows: Let `C` denote the
2933
+ type `iterator_traits<iterator_t<Base>>::iterator_category`.
2934
+
2935
+ - If
2936
+ `is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>`
2937
+ is `true`, then
2938
+ - if `C` models `derived_from<contiguous_iterator_tag>`,
2939
+ `iterator_category` denotes `random_access_iterator_tag`;
2940
+ - otherwise, `iterator_category` denotes `C`.
2941
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
2942
+
2943
+ ``` cpp
2944
+ constexpr iterator(Parent& parent, iterator_t<Base> current);
2945
+ ```
2946
+
2947
+ *Effects:* Initializes *current\_* with `std::move(current)` and
2948
+ *parent\_* with `addressof(parent)`.
2949
+
2950
+ ``` cpp
2951
+ constexpr iterator(iterator<!Const> i)
2952
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2953
+ ```
2954
+
2955
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
2956
+ and *parent\_* with `i.`*`parent_`*.
2957
+
2958
+ ``` cpp
2959
+ constexpr iterator_t<Base> base() const &
2960
+ requires copyable<iterator_t<Base>>;
2961
+ ```
2962
+
2963
+ *Effects:* Equivalent to: `return `*`current_`*`;`
2964
+
2965
+ ``` cpp
2966
+ constexpr iterator_t<Base> base() &&;
2967
+ ```
2968
+
2969
+ *Effects:* Equivalent to: `return std::move(current_);`
2970
+
2971
+ ``` cpp
2972
+ constexpr iterator& operator++();
2973
+ ```
2974
+
2975
+ *Effects:* Equivalent to:
2976
+
2977
+ ``` cpp
2978
+ ++current_;
2979
+ return *this;
2980
+ ```
2981
+
2982
+ ``` cpp
2983
+ constexpr void operator++(int);
2984
+ ```
2985
+
2986
+ *Effects:* Equivalent to `++current_`.
2987
+
2988
+ ``` cpp
2989
+ constexpr iterator operator++(int) requires forward_range<Base>;
2990
+ ```
2991
+
2992
+ *Effects:* Equivalent to:
2993
+
2994
+ ``` cpp
2995
+ auto tmp = *this;
2996
+ ++*this;
2997
+ return tmp;
2998
+ ```
2999
+
3000
+ ``` cpp
3001
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
3002
+ ```
3003
+
3004
+ *Effects:* Equivalent to:
3005
+
3006
+ ``` cpp
3007
+ --current_;
3008
+ return *this;
3009
+ ```
3010
+
3011
+ ``` cpp
3012
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
3013
+ ```
3014
+
3015
+ *Effects:* Equivalent to:
3016
+
3017
+ ``` cpp
3018
+ auto tmp = *this;
3019
+ --*this;
3020
+ return tmp;
3021
+ ```
3022
+
3023
+ ``` cpp
3024
+ constexpr iterator& operator+=(difference_type n)
3025
+ requires random_access_range<Base>;
3026
+ ```
3027
+
3028
+ *Effects:* Equivalent to:
3029
+
3030
+ ``` cpp
3031
+ current_ += n;
3032
+ return *this;
3033
+ ```
3034
+
3035
+ ``` cpp
3036
+ constexpr iterator& operator-=(difference_type n)
3037
+ requires random_access_range<Base>;
3038
+ ```
3039
+
3040
+ *Effects:* Equivalent to:
3041
+
3042
+ ``` cpp
3043
+ current_ -= n;
3044
+ return *this;
3045
+ ```
3046
+
3047
+ ``` cpp
3048
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
3049
+ requires equality_comparable<iterator_t<Base>>;
3050
+ ```
3051
+
3052
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
3053
+
3054
+ ``` cpp
3055
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
3056
+ requires random_access_range<Base>;
3057
+ ```
3058
+
3059
+ *Effects:* Equivalent to: `return x.`*`current_`*` < y.`*`current_`*`;`
3060
+
3061
+ ``` cpp
3062
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
3063
+ requires random_access_range<Base>;
3064
+ ```
3065
+
3066
+ *Effects:* Equivalent to: `return y < x;`
3067
+
3068
+ ``` cpp
3069
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
3070
+ requires random_access_range<Base>;
3071
+ ```
3072
+
3073
+ *Effects:* Equivalent to: `return !(y < x);`
3074
+
3075
+ ``` cpp
3076
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
3077
+ requires random_access_range<Base>;
3078
+ ```
3079
+
3080
+ *Effects:* Equivalent to: `return !(x < y);`
3081
+
3082
+ ``` cpp
3083
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
3084
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
3085
+ ```
3086
+
3087
+ *Effects:* Equivalent to:
3088
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
3089
+
3090
+ ``` cpp
3091
+ friend constexpr iterator operator+(iterator i, difference_type n)
3092
+ requires random_access_range<Base>;
3093
+ friend constexpr iterator operator+(difference_type n, iterator i)
3094
+ requires random_access_range<Base>;
3095
+ ```
3096
+
3097
+ *Effects:* Equivalent to:
3098
+ `return iterator{*i.`*`parent_`*`, i.`*`current_`*` + n};`
3099
+
3100
+ ``` cpp
3101
+ friend constexpr iterator operator-(iterator i, difference_type n)
3102
+ requires random_access_range<Base>;
3103
+ ```
3104
+
3105
+ *Effects:* Equivalent to:
3106
+ `return iterator{*i.`*`parent_`*`, i.`*`current_`*` - n};`
3107
+
3108
+ ``` cpp
3109
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
3110
+ requires random_access_range<Base>;
3111
+ ```
3112
+
3113
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
3114
+
3115
+ ``` cpp
3116
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
3117
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
3118
+ requires indirectly_swappable<iterator_t<Base>>;
3119
+ ```
3120
+
3121
+ *Effects:* Equivalent to
3122
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
3123
+
3124
+ #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
3125
+
3126
+ ``` cpp
3127
+ namespace std::ranges {
3128
+ template<input_range V, copy_constructible F>
3129
+ requires view<V> && is_object_v<F> &&
3130
+ regular_invocable<F&, range_reference_t<V>> &&
3131
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
3132
+ template<bool Const>
3133
+ class transform_view<V, F>::sentinel {
3134
+ private:
3135
+ using Parent = // exposition only
3136
+ conditional_t<Const, const transform_view, transform_view>;
3137
+ using Base = conditional_t<Const, const V, V>; // exposition only
3138
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
3139
+ public:
3140
+ sentinel() = default;
3141
+ constexpr explicit sentinel(sentinel_t<Base> end);
3142
+ constexpr sentinel(sentinel<!Const> i)
3143
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3144
+
3145
+ constexpr sentinel_t<Base> base() const;
3146
+
3147
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
3148
+
3149
+ friend constexpr range_difference_t<Base>
3150
+ operator-(const iterator<Const>& x, const sentinel& y)
3151
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3152
+ friend constexpr range_difference_t<Base>
3153
+ operator-(const sentinel& y, const iterator<Const>& x)
3154
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3155
+ };
3156
+ }
3157
+ ```
3158
+
3159
+ ``` cpp
3160
+ constexpr explicit sentinel(sentinel_t<Base> end);
3161
+ ```
3162
+
3163
+ *Effects:* Initializes *end\_* with `end`.
3164
+
3165
+ ``` cpp
3166
+ constexpr sentinel(sentinel<!Const> i)
3167
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3168
+ ```
3169
+
3170
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
3171
+
3172
+ ``` cpp
3173
+ constexpr sentinel_t<Base> base() const;
3174
+ ```
3175
+
3176
+ *Effects:* Equivalent to: `return `*`end_`*`;`
3177
+
3178
+ ``` cpp
3179
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
3180
+ ```
3181
+
3182
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
3183
+
3184
+ ``` cpp
3185
+ friend constexpr range_difference_t<Base>
3186
+ operator-(const iterator<Const>& x, const sentinel& y)
3187
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3188
+ ```
3189
+
3190
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
3191
+
3192
+ ``` cpp
3193
+ friend constexpr range_difference_t<Base>
3194
+ operator-(const sentinel& y, const iterator<Const>& x)
3195
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3196
+ ```
3197
+
3198
+ *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
3199
+
3200
+ ### Take view <a id="range.take">[[range.take]]</a>
3201
+
3202
+ #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
3203
+
3204
+ `take_view` produces a `view` of the first N elements from another
3205
+ `view`, or all the elements if the adapted `view` contains fewer than N.
3206
+
3207
+ The name `views::take` denotes a range adaptor object
3208
+ [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
3209
+ `remove_cvref_t<decltype((E))>`, and let `D` be
3210
+ `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
3211
+ `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
3212
+ expression `views::take(E, F)` is expression-equivalent to:
3213
+
3214
+ - If `T` is a specialization of `ranges::empty_view`
3215
+ [[range.empty.view]], then `((void) F, decay-copy(E))`.
3216
+ - Otherwise, if `T` models `random_access_range` and `sized_range` and
3217
+ is
3218
+ - a specialization of `span` [[views.span]] where
3219
+ `T::extent == dynamic_extent`,
3220
+ - a specialization of `basic_string_view` [[string.view]],
3221
+ - a specialization of `ranges::iota_view` [[range.iota.view]], or
3222
+ - a specialization of `ranges::subrange` [[range.subrange]],
3223
+
3224
+ then
3225
+ `T{ranges::begin(E), ranges::begin(E) + min<D>(ranges::size(E), F)}`,
3226
+ except that `E` is evaluated only once.
3227
+ - Otherwise, `ranges::take_view{E, F}`.
3228
+
3229
+ [*Example 1*:
3230
+
3231
+ ``` cpp
3232
+ vector<int> is{0,1,2,3,4,5,6,7,8,9};
3233
+ take_view few{is, 5};
3234
+ for (int i : few)
3235
+ cout << i << ' '; // prints: 0 1 2 3 4
3236
+ ```
3237
+
3238
+ — *end example*]
3239
+
3240
+ #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
3241
+
3242
+ ``` cpp
3243
+ namespace std::ranges {
3244
+ template<view V>
3245
+ class take_view : public view_interface<take_view<V>> {
3246
+ private:
3247
+ V base_ = V(); // exposition only
3248
+ range_difference_t<V> count_ = 0; // exposition only
3249
+ // [range.take.sentinel], class template take_view::sentinel
3250
+ template<bool> struct sentinel; // exposition only
3251
+ public:
3252
+ take_view() = default;
3253
+ constexpr take_view(V base, range_difference_t<V> count);
3254
+
3255
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
3256
+ constexpr V base() && { return std::move(base_); }
3257
+
3258
+ constexpr auto begin() requires (!simple-view<V>) {
3259
+ if constexpr (sized_range<V>) {
3260
+ if constexpr (random_access_range<V>)
3261
+ return ranges::begin(base_);
3262
+ else {
3263
+ auto sz = size();
3264
+ return counted_iterator{ranges::begin(base_), sz};
3265
+ }
3266
+ } else
3267
+ return counted_iterator{ranges::begin(base_), count_};
3268
+ }
3269
+
3270
+ constexpr auto begin() const requires range<const V> {
3271
+ if constexpr (sized_range<const V>) {
3272
+ if constexpr (random_access_range<const V>)
3273
+ return ranges::begin(base_);
3274
+ else {
3275
+ auto sz = size();
3276
+ return counted_iterator{ranges::begin(base_), sz};
3277
+ }
3278
+ } else
3279
+ return counted_iterator{ranges::begin(base_), count_};
3280
+ }
3281
+
3282
+ constexpr auto end() requires (!simple-view<V>) {
3283
+ if constexpr (sized_range<V>) {
3284
+ if constexpr (random_access_range<V>)
3285
+ return ranges::begin(base_) + size();
3286
+ else
3287
+ return default_sentinel;
3288
+ } else
3289
+ return sentinel<false>{ranges::end(base_)};
3290
+ }
3291
+
3292
+ constexpr auto end() const requires range<const V> {
3293
+ if constexpr (sized_range<const V>) {
3294
+ if constexpr (random_access_range<const V>)
3295
+ return ranges::begin(base_) + size();
3296
+ else
3297
+ return default_sentinel;
3298
+ } else
3299
+ return sentinel<true>{ranges::end(base_)};
3300
+ }
3301
+
3302
+ constexpr auto size() requires sized_range<V> {
3303
+ auto n = ranges::size(base_);
3304
+ return ranges::min(n, static_cast<decltype(n)>(count_));
3305
+ }
3306
+
3307
+ constexpr auto size() const requires sized_range<const V> {
3308
+ auto n = ranges::size(base_);
3309
+ return ranges::min(n, static_cast<decltype(n)>(count_));
3310
+ }
3311
+ };
3312
+
3313
+ template<range R>
3314
+ take_view(R&&, range_difference_t<R>)
3315
+ -> take_view<views::all_t<R>>;
3316
+ }
3317
+ ```
3318
+
3319
+ ``` cpp
3320
+ constexpr take_view(V base, range_difference_t<V> count);
3321
+ ```
3322
+
3323
+ *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
3324
+ with `count`.
3325
+
3326
+ #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
3327
+
3328
+ ``` cpp
3329
+ namespace std::ranges {
3330
+ template<view V>
3331
+ template<bool Const>
3332
+ class take_view<V>::sentinel {
3333
+ private:
3334
+ using Base = conditional_t<Const, const V, V>; // exposition only
3335
+ using CI = counted_iterator<iterator_t<Base>>; // exposition only
3336
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
3337
+ public:
3338
+ sentinel() = default;
3339
+ constexpr explicit sentinel(sentinel_t<Base> end);
3340
+ constexpr sentinel(sentinel<!Const> s)
3341
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3342
+
3343
+ constexpr sentinel_t<Base> base() const;
3344
+
3345
+ friend constexpr bool operator==(const CI& y, const sentinel& x);
3346
+ };
3347
+ }
3348
+ ```
3349
+
3350
+ ``` cpp
3351
+ constexpr explicit sentinel(sentinel_t<Base> end);
3352
+ ```
3353
+
3354
+ *Effects:* Initializes *end\_* with `end`.
3355
+
3356
+ ``` cpp
3357
+ constexpr sentinel(sentinel<!Const> s)
3358
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3359
+ ```
3360
+
3361
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
3362
+
3363
+ ``` cpp
3364
+ constexpr sentinel_t<Base> base() const;
3365
+ ```
3366
+
3367
+ *Effects:* Equivalent to: `return `*`end_`*`;`
3368
+
3369
+ ``` cpp
3370
+ friend constexpr bool operator==(const CI& y, const sentinel& x);
3371
+ ```
3372
+
3373
+ *Effects:* Equivalent to:
3374
+ `return y.count() == 0 || y.base() == x.`*`end_`*`;`
3375
+
3376
+ ### Take while view <a id="range.take.while">[[range.take.while]]</a>
3377
+
3378
+ #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
3379
+
3380
+ Given a unary predicate `pred` and a `view` `r`, `take_while_view`
3381
+ produces a `view` of the range \[`begin(r)`,
3382
+ `ranges::find_if_not(r, pred)`).
3383
+
3384
+ The name `views::take_while` denotes a range adaptor object
3385
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3386
+ expression `views::take_while(E, F)` is expression-equivalent to
3387
+ `take_while_view{E, F}`.
3388
+
3389
+ [*Example 1*:
3390
+
3391
+ ``` cpp
3392
+ auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
3393
+ auto small = [](const auto x) noexcept { return x < 5; };
3394
+ auto small_ints = istream_view<int>(input) | views::take_while(small);
3395
+ for (const auto i : small_ints) {
3396
+ cout << i << ' '; // prints 0 1 2 3 4
3397
+ }
3398
+ auto i = 0;
3399
+ input >> i;
3400
+ cout << i; // prints 6
3401
+ ```
3402
+
3403
+ — *end example*]
3404
+
3405
+ #### Class template `take_while_view` <a id="range.take.while.view">[[range.take.while.view]]</a>
3406
+
3407
+ ``` cpp
3408
+ namespace std::ranges {
3409
+ template<view V, class Pred>
3410
+ requires input_range<V> && is_object_v<Pred> &&
3411
+ indirect_unary_predicate<const Pred, iterator_t<V>>
3412
+ class take_while_view : public view_interface<take_while_view<V, Pred>> {
3413
+ // [range.take.while.sentinel], class template take_while_view::sentinel
3414
+ template<bool> class sentinel; // exposition only
3415
+
3416
+ V base_ = V(); // exposition only
3417
+ semiregular-box<Pred> pred_; // exposition only
3418
+
3419
+ public:
3420
+ take_while_view() = default;
3421
+ constexpr take_while_view(V base, Pred pred);
3422
+
3423
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
3424
+ constexpr V base() && { return std::move(base_); }
3425
+
3426
+ constexpr const Pred& pred() const;
3427
+
3428
+ constexpr auto begin() requires (!simple-view<V>)
3429
+ { return ranges::begin(base_); }
3430
+
3431
+ constexpr auto begin() const requires range<const V>
3432
+ { return ranges::begin(base_); }
3433
+
3434
+ constexpr auto end() requires (!simple-view<V>)
3435
+ { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
3436
+
3437
+ constexpr auto end() const requires range<const V>
3438
+ { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
3439
+ };
3440
+
3441
+ template<class R, class Pred>
3442
+ take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
3443
+ }
3444
+ ```
3445
+
3446
+ ``` cpp
3447
+ constexpr take_while_view(V base, Pred pred);
3448
+ ```
3449
+
3450
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
3451
+ `std::move(pred)`.
3452
+
3453
+ ``` cpp
3454
+ constexpr const Pred& pred() const;
3455
+ ```
3456
+
3457
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
3458
+
3459
+ #### Class template `take_while_view::sentinel` <a id="range.take.while.sentinel">[[range.take.while.sentinel]]</a>
3460
+
3461
+ ``` cpp
3462
+ namespace std::ranges {
3463
+ template<view V, class Pred>
3464
+ requires input_range<V> && is_object_v<Pred> &&
3465
+ indirect_unary_predicate<const Pred, iterator_t<V>>
3466
+ template<bool Const>
3467
+ class take_while_view<V, Pred>::sentinel { // exposition only
3468
+ using Base = conditional_t<Const, const V, V>; // exposition only
3469
+
3470
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
3471
+ const Pred* pred_ = nullptr; // exposition only
3472
+ public:
3473
+ sentinel() = default;
3474
+ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
3475
+ constexpr sentinel(sentinel<!Const> s)
3476
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3477
+
3478
+ constexpr sentinel_t<Base> base() const { return end_; }
3479
+
3480
+ friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
3481
+ };
3482
+ }
3483
+ ```
3484
+
3485
+ ``` cpp
3486
+ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
3487
+ ```
3488
+
3489
+ *Effects:* Initializes *end\_* with `end` and *pred\_* with `pred`.
3490
+
3491
+ ``` cpp
3492
+ constexpr sentinel(sentinel<!Const> s)
3493
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3494
+ ```
3495
+
3496
+ *Effects:* Initializes *end\_* with `s.`*`end_`* and *pred\_* with
3497
+ `s.`*`pred_`*.
3498
+
3499
+ ``` cpp
3500
+ friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
3501
+ ```
3502
+
3503
+ *Effects:* Equivalent to:
3504
+ `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
3505
+
3506
+ ### Drop view <a id="range.drop">[[range.drop]]</a>
3507
+
3508
+ #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
3509
+
3510
+ `drop_view` produces a `view` excluding the first N elements from
3511
+ another `view`, or an empty range if the adapted `view` contains fewer
3512
+ than N elements.
3513
+
3514
+ The name `views::drop` denotes a range adaptor object
3515
+ [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
3516
+ `remove_cvref_t<decltype((E))>`, and let `D` be
3517
+ `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
3518
+ `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
3519
+ expression `views::drop(E, F)` is expression-equivalent to:
3520
+
3521
+ - If `T` is a specialization of `ranges::empty_view`
3522
+ [[range.empty.view]], then `((void) F, decay-copy(E))`.
3523
+ - Otherwise, if `T` models `random_access_range` and `sized_range` and
3524
+ is
3525
+ - a specialization of `span` [[views.span]] where
3526
+ `T::extent == dynamic_extent`,
3527
+ - a specialization of `basic_string_view` [[string.view]],
3528
+ - a specialization of `ranges::iota_view` [[range.iota.view]], or
3529
+ - a specialization of `ranges::subrange` [[range.subrange]],
3530
+
3531
+ then
3532
+ `T{ranges::begin(E) + min<D>(ranges::size(E), F), ranges::end(E)}`,
3533
+ except that `E` is evaluated only once.
3534
+ - Otherwise, `ranges::drop_view{E, F}`.
3535
+
3536
+ [*Example 1*:
3537
+
3538
+ ``` cpp
3539
+ auto ints = views::iota(0) | views::take(10);
3540
+ auto latter_half = drop_view{ints, 5};
3541
+ for (auto i : latter_half) {
3542
+ cout << i << ' '; // prints 5 6 7 8 9
3543
+ }
3544
+ ```
3545
+
3546
+ — *end example*]
3547
+
3548
+ #### Class template `drop_view` <a id="range.drop.view">[[range.drop.view]]</a>
3549
+
3550
+ ``` cpp
3551
+ namespace std::ranges {
3552
+ template<view V>
3553
+ class drop_view : public view_interface<drop_view<V>> {
3554
+ public:
3555
+ drop_view() = default;
3556
+ constexpr drop_view(V base, range_difference_t<V> count);
3557
+
3558
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
3559
+ constexpr V base() && { return std::move(base_); }
3560
+
3561
+ constexpr auto begin()
3562
+ requires (!(simple-view<V> && random_access_range<V>));
3563
+ constexpr auto begin() const
3564
+ requires random_access_range<const V>;
3565
+
3566
+ constexpr auto end()
3567
+ requires (!simple-view<V>)
3568
+ { return ranges::end(base_); }
3569
+
3570
+ constexpr auto end() const
3571
+ requires range<const V>
3572
+ { return ranges::end(base_); }
3573
+
3574
+ constexpr auto size()
3575
+ requires sized_range<V>
3576
+ {
3577
+ const auto s = ranges::size(base_);
3578
+ const auto c = static_cast<decltype(s)>(count_);
3579
+ return s < c ? 0 : s - c;
3580
+ }
3581
+
3582
+ constexpr auto size() const
3583
+ requires sized_range<const V>
3584
+ {
3585
+ const auto s = ranges::size(base_);
3586
+ const auto c = static_cast<decltype(s)>(count_);
3587
+ return s < c ? 0 : s - c;
3588
+ }
3589
+ private:
3590
+ V base_ = V(); // exposition only
3591
+ range_difference_t<V> count_ = 0; // exposition only
3592
+ };
3593
+
3594
+ template<class R>
3595
+ drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
3596
+ }
3597
+ ```
3598
+
3599
+ ``` cpp
3600
+ constexpr drop_view(V base, range_difference_t<V> count);
3601
+ ```
3602
+
3603
+ *Preconditions:* `count >= 0` is `true`.
3604
+
3605
+ *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
3606
+ with `count`.
3607
+
3608
+ ``` cpp
3609
+ constexpr auto begin()
3610
+ requires (!(simple-view<V> && random_access_range<V>));
3611
+ constexpr auto begin() const
3612
+ requires random_access_range<const V>;
3613
+ ```
3614
+
3615
+ *Returns:*
3616
+ `ranges::next(ranges::begin(base_), count_, ranges::end(base_))`.
3617
+
3618
+ *Remarks:* In order to provide the amortized constant-time complexity
3619
+ required by the `range` concept when `drop_view` models `forward_range`,
3620
+ the first overload caches the result within the `drop_view` for use on
3621
+ subsequent calls.
3622
+
3623
+ [*Note 1*: Without this, applying a `reverse_view` over a `drop_view`
3624
+ would have quadratic iteration complexity. — *end note*]
3625
+
3626
+ ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
3627
+
3628
+ #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
3629
+
3630
+ Given a unary predicate `pred` and a `view` `r`, `drop_while_view`
3631
+ produces a `view` of the range \[`ranges::find_if_not(r, pred)`,
3632
+ `ranges::end(r)`).
3633
+
3634
+ The name `views::drop_while` denotes a range adaptor object
3635
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3636
+ expression `views::drop_while(E, F)` is expression-equivalent to
3637
+ `drop_while_view{E, F}`.
3638
+
3639
+ [*Example 1*:
3640
+
3641
+ ``` cpp
3642
+ constexpr auto source = " \t \t \t hello there";
3643
+ auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
3644
+ auto skip_ws = drop_while_view{source, is_invisible};
3645
+ for (auto c : skip_ws) {
3646
+ cout << c; // prints hello there with no leading space
3647
+ }
3648
+ ```
3649
+
3650
+ — *end example*]
3651
+
3652
+ #### Class template `drop_while_view` <a id="range.drop.while.view">[[range.drop.while.view]]</a>
3653
+
3654
+ ``` cpp
3655
+ namespace std::ranges {
3656
+ template<view V, class Pred>
3657
+ requires input_range<V> && is_object_v<Pred> &&
3658
+ indirect_unary_predicate<const Pred, iterator_t<V>>
3659
+ class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
3660
+ public:
3661
+ drop_while_view() = default;
3662
+ constexpr drop_while_view(V base, Pred pred);
3663
+
3664
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
3665
+ constexpr V base() && { return std::move(base_); }
3666
+
3667
+ constexpr const Pred& pred() const;
3668
+
3669
+ constexpr auto begin();
3670
+
3671
+ constexpr auto end()
3672
+ { return ranges::end(base_); }
3673
+
3674
+ private:
3675
+ V base_ = V(); // exposition only
3676
+ semiregular-box<Pred> pred_; // exposition only
3677
+ };
3678
+
3679
+ template<class R, class Pred>
3680
+ drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
3681
+ }
3682
+ ```
3683
+
3684
+ ``` cpp
3685
+ constexpr drop_while_view(V base, Pred pred);
3686
+ ```
3687
+
3688
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
3689
+ `std::move(pred)`.
3690
+
3691
+ ``` cpp
3692
+ constexpr const Pred& pred() const;
3693
+ ```
3694
+
3695
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
3696
+
3697
+ ``` cpp
3698
+ constexpr auto begin();
3699
+ ```
3700
+
3701
+ *Returns:* `ranges::find_if_not(base_, cref(*pred_))`.
3702
+
3703
+ *Remarks:* In order to provide the amortized constant-time complexity
3704
+ required by the `range` concept when `drop_while_view` models
3705
+ `forward_range`, the first call caches the result within the
3706
+ `drop_while_view` for use on subsequent calls.
3707
+
3708
+ [*Note 1*: Without this, applying a `reverse_view` over a
3709
+ `drop_while_view` would have quadratic iteration
3710
+ complexity. — *end note*]
3711
+
3712
+ ### Join view <a id="range.join">[[range.join]]</a>
3713
+
3714
+ #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
3715
+
3716
+ `join_view` flattens a `view` of ranges into a `view`.
3717
+
3718
+ The name `views::join` denotes a range adaptor object
3719
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
3720
+ `views::join(E)` is expression-equivalent to `join_view{E}`.
3721
+
3722
+ [*Example 1*:
3723
+
3724
+ ``` cpp
3725
+ vector<string> ss{"hello", " ", "world", "!"};
3726
+ join_view greeting{ss};
3727
+ for (char ch : greeting)
3728
+ cout << ch; // prints: hello world!
3729
+ ```
3730
+
3731
+ — *end example*]
3732
+
3733
+ #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
3734
+
3735
+ ``` cpp
3736
+ namespace std::ranges {
3737
+ template<input_range V>
3738
+ requires view<V> && input_range<range_reference_t<V>> &&
3739
+ (is_reference_v<range_reference_t<V>> ||
3740
+ view<range_value_t<V>>)
3741
+ class join_view : public view_interface<join_view<V>> {
3742
+ private:
3743
+ using InnerRng = // exposition only
3744
+ range_reference_t<V>;
3745
+ // [range.join.iterator], class template join_view::iterator
3746
+ template<bool Const>
3747
+ struct iterator; // exposition only
3748
+ // [range.join.sentinel], class template join_view::sentinel
3749
+ template<bool Const>
3750
+ struct sentinel; // exposition only
3751
+
3752
+ V base_ = V(); // exposition only
3753
+ views::all_t<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng>
3754
+ views::all_t<InnerRng>();
3755
+ public:
3756
+ join_view() = default;
3757
+ constexpr explicit join_view(V base);
3758
+
3759
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
3760
+ constexpr V base() && { return std::move(base_); }
3761
+
3762
+ constexpr auto begin() {
3763
+ constexpr bool use_const = simple-view<V> &&
3764
+ is_reference_v<range_reference_t<V>>;
3765
+ return iterator<use_const>{*this, ranges::begin(base_)};
3766
+ }
3767
+
3768
+ constexpr auto begin() const
3769
+ requires input_range<const V> &&
3770
+ is_reference_v<range_reference_t<const V>> {
3771
+ return iterator<true>{*this, ranges::begin(base_)};
3772
+ }
3773
+
3774
+ constexpr auto end() {
3775
+ if constexpr (forward_range<V> &&
3776
+ is_reference_v<InnerRng> && forward_range<InnerRng> &&
3777
+ common_range<V> && common_range<InnerRng>)
3778
+ return iterator<simple-view<V>>{*this, ranges::end(base_)};
3779
+ else
3780
+ return sentinel<simple-view<V>>{*this};
3781
+ }
3782
+
3783
+ constexpr auto end() const
3784
+ requires input_range<const V> &&
3785
+ is_reference_v<range_reference_t<const V>> {
3786
+ if constexpr (forward_range<const V> &&
3787
+ is_reference_v<range_reference_t<const V>> &&
3788
+ forward_range<range_reference_t<const V>> &&
3789
+ common_range<const V> &&
3790
+ common_range<range_reference_t<const V>>)
3791
+ return iterator<true>{*this, ranges::end(base_)};
3792
+ else
3793
+ return sentinel<true>{*this};
3794
+ }
3795
+ };
3796
+
3797
+ template<class R>
3798
+ explicit join_view(R&&) -> join_view<views::all_t<R>>;
3799
+ }
3800
+ ```
3801
+
3802
+ ``` cpp
3803
+ constexpr explicit join_view(V base);
3804
+ ```
3805
+
3806
+ *Effects:* Initializes *base\_* with `std::move(base)`.
3807
+
3808
+ #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
3809
+
3810
+ ``` cpp
3811
+ namespace std::ranges {
3812
+ template<input_range V>
3813
+ requires view<V> && input_range<range_reference_t<V>> &&
3814
+ (is_reference_v<range_reference_t<V>> ||
3815
+ view<range_value_t<V>>)
3816
+ template<bool Const>
3817
+ struct join_view<V>::iterator {
3818
+ private:
3819
+ using Parent = // exposition only
3820
+ conditional_t<Const, const join_view, join_view>;
3821
+ using Base = conditional_t<Const, const V, V>; // exposition only
3822
+
3823
+ static constexpr bool ref-is-glvalue = // exposition only
3824
+ is_reference_v<range_reference_t<Base>>;
3825
+
3826
+ iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
3827
+ iterator_t<range_reference_t<Base>> inner_ = // exposition only
3828
+ iterator_t<range_reference_t<Base>>();
3829
+ Parent* parent_ = nullptr; // exposition only
3830
+
3831
+ constexpr void satisfy(); // exposition only
3832
+ public:
3833
+ using iterator_concept = see below;
3834
+ using iterator_category = see below;
3835
+ using value_type = range_value_t<range_reference_t<Base>>;
3836
+ using difference_type = see below;
3837
+
3838
+ iterator() = default;
3839
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
3840
+ constexpr iterator(iterator<!Const> i)
3841
+ requires Const &&
3842
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
3843
+ convertible_to<iterator_t<InnerRng>,
3844
+ iterator_t<range_reference_t<Base>>>;
3845
+
3846
+ constexpr decltype(auto) operator*() const { return *inner_; }
3847
+
3848
+ constexpr iterator_t<Base> operator->() const
3849
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
3850
+
3851
+ constexpr iterator& operator++();
3852
+ constexpr void operator++(int);
3853
+ constexpr iterator operator++(int)
3854
+ requires ref-is-glvalue && forward_range<Base> &&
3855
+ forward_range<range_reference_t<Base>>;
3856
+
3857
+ constexpr iterator& operator--()
3858
+ requires ref-is-glvalue && bidirectional_range<Base> &&
3859
+ bidirectional_range<range_reference_t<Base>> &&
3860
+ common_range<range_reference_t<Base>>;
3861
+
3862
+ constexpr iterator operator--(int)
3863
+ requires ref-is-glvalue && bidirectional_range<Base> &&
3864
+ bidirectional_range<range_reference_t<Base>> &&
3865
+ common_range<range_reference_t<Base>>;
3866
+
3867
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
3868
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
3869
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
3870
+
3871
+ friend constexpr decltype(auto) iter_move(const iterator& i)
3872
+ noexcept(noexcept(ranges::iter_move(i.inner_))) {
3873
+ return ranges::iter_move(i.inner_);
3874
+ }
3875
+
3876
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
3877
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
3878
+ };
3879
+ }
3880
+ ```
3881
+
3882
+ `iterator::iterator_concept` is defined as follows:
3883
+
3884
+ - If *`ref-is-glvalue`* is `true` and *`Base`* and
3885
+ `range_reference_t<Base>` each model `bidirectional_range`, then
3886
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
3887
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
3888
+ `range_reference_t<Base>` each model , then `iterator_concept` denotes
3889
+ `forward_iterator_tag`.
3890
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
3891
+
3892
+ `iterator::iterator_category` is defined as follows:
3893
+
3894
+ - Let *OUTERC* denote
3895
+ `iterator_traits<iterator_t<Base>>::iterator_category`, and let
3896
+ *INNERC* denote
3897
+ `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
3898
+ - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
3899
+ `derived_from<bidirectional_iterator_tag>`, `iterator_category`
3900
+ denotes `bidirectional_iterator_tag`.
3901
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
3902
+ each model `derived_from<forward_iterator_tag>`, `iterator_category`
3903
+ denotes `forward_iterator_tag`.
3904
+ - Otherwise, if *OUTERC* and *INNERC* each model
3905
+ `derived_from<input_iterator_tag>`, `iterator_category` denotes
3906
+ `input_iterator_tag`.
3907
+ - Otherwise, `iterator_category` denotes `output_iterator_tag`.
3908
+
3909
+ `iterator::difference_type` denotes the type:
3910
+
3911
+ ``` cpp
3912
+ common_type_t<
3913
+ range_difference_t<Base>,
3914
+ range_difference_t<range_reference_t<Base>>>
3915
+ ```
3916
+
3917
+ `join_view` iterators use the *`satisfy`* function to skip over empty
3918
+ inner ranges.
3919
+
3920
+ ``` cpp
3921
+ constexpr void satisfy(); // exposition only
3922
+ ```
3923
+
3924
+ *Effects:* Equivalent to:
3925
+
3926
+ ``` cpp
3927
+ auto update_inner = [this](range_reference_t<Base> x) -> auto& {
3928
+ if constexpr (ref-is-glvalue) // x is a reference
3929
+ return x;
3930
+ else
3931
+ return (parent_->inner_ = views::all(std::move(x)));
3932
+ };
3933
+
3934
+ for (; outer_ != ranges::end(parent_->base_); ++outer_) {
3935
+ auto& inner = update_inner(*outer_);
3936
+ inner_ = ranges::begin(inner);
3937
+ if (inner_ != ranges::end(inner))
3938
+ return;
3939
+ }
3940
+ if constexpr (ref-is-glvalue)
3941
+ inner_ = iterator_t<range_reference_t<Base>>();
3942
+ ```
3943
+
3944
+ ``` cpp
3945
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
3946
+ ```
3947
+
3948
+ *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
3949
+ with `addressof(parent)`; then calls *`satisfy`*`()`.
3950
+
3951
+ ``` cpp
3952
+ constexpr iterator(iterator<!Const> i)
3953
+ requires Const &&
3954
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
3955
+ convertible_to<iterator_t<InnerRng>,
3956
+ iterator_t<range_reference_t<Base>>>;
3957
+ ```
3958
+
3959
+ *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
3960
+ *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
3961
+ `i.`*`parent_`*.
3962
+
3963
+ ``` cpp
3964
+ constexpr iterator_t<Base> operator->() const
3965
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
3966
+ ```
3967
+
3968
+ *Effects:* Equivalent to `return `*`inner_`*`;`
3969
+
3970
+ ``` cpp
3971
+ constexpr iterator& operator++();
3972
+ ```
3973
+
3974
+ Let *`inner-range`* be:
3975
+
3976
+ - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
3977
+ - Otherwise, *`parent_`*`->`*`inner_`*.
3978
+
3979
+ *Effects:* Equivalent to:
3980
+
3981
+ ``` cpp
3982
+ auto&& inner_rng = inner-range;
3983
+ if (++inner_ == ranges::end(inner_rng)) {
3984
+ ++outer_;
3985
+ satisfy();
3986
+ }
3987
+ return *this;
3988
+ ```
3989
+
3990
+ ``` cpp
3991
+ constexpr void operator++(int);
3992
+ ```
3993
+
3994
+ *Effects:* Equivalent to: `++*this`.
3995
+
3996
+ ``` cpp
3997
+ constexpr iterator operator++(int)
3998
+ requires ref-is-glvalue && forward_range<Base> &&
3999
+ forward_range<range_reference_t<Base>>;
4000
+ ```
4001
+
4002
+ *Effects:* Equivalent to:
4003
+
4004
+ ``` cpp
4005
+ auto tmp = *this;
4006
+ ++*this;
4007
+ return tmp;
4008
+ ```
4009
+
4010
+ ``` cpp
4011
+ constexpr iterator& operator--()
4012
+ requires ref-is-glvalue && bidirectional_range<Base> &&
4013
+ bidirectional_range<range_reference_t<Base>> &&
4014
+ common_range<range_reference_t<Base>>;
4015
+ ```
4016
+
4017
+ *Effects:* Equivalent to:
4018
+
4019
+ ``` cpp
4020
+ if (outer_ == ranges::end(parent_->base_))
4021
+ inner_ = ranges::end(*--outer_);
4022
+ while (inner_ == ranges::begin(*outer_))
4023
+ inner_ = ranges::end(*--outer_);
4024
+ --inner_;
4025
+ return *this;
4026
+ ```
4027
+
4028
+ ``` cpp
4029
+ constexpr iterator operator--(int)
4030
+ requires ref-is-glvalue && bidirectional_range<Base> &&
4031
+ bidirectional_range<range_reference_t<Base>> &&
4032
+ common_range<range_reference_t<Base>>;
4033
+ ```
4034
+
4035
+ *Effects:* Equivalent to:
4036
+
4037
+ ``` cpp
4038
+ auto tmp = *this;
4039
+ --*this;
4040
+ return tmp;
4041
+ ```
4042
+
4043
+ ``` cpp
4044
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
4045
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
4046
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
4047
+ ```
4048
+
4049
+ *Effects:* Equivalent to:
4050
+ `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
4051
+
4052
+ ``` cpp
4053
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
4054
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
4055
+ ```
4056
+
4057
+ *Effects:* Equivalent to:
4058
+ `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
4059
+
4060
+ #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
4061
+
4062
+ ``` cpp
4063
+ namespace std::ranges {
4064
+ template<input_range V>
4065
+ requires view<V> && input_range<range_reference_t<V>> &&
4066
+ (is_reference_v<range_reference_t<V>> ||
4067
+ view<range_value_t<V>>)
4068
+ template<bool Const>
4069
+ struct join_view<V>::sentinel {
4070
+ private:
4071
+ using Parent = // exposition only
4072
+ conditional_t<Const, const join_view, join_view>;
4073
+ using Base = conditional_t<Const, const V, V>; // exposition only
4074
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4075
+ public:
4076
+ sentinel() = default;
4077
+
4078
+ constexpr explicit sentinel(Parent& parent);
4079
+ constexpr sentinel(sentinel<!Const> s)
4080
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4081
+
4082
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
4083
+ };
4084
+ }
4085
+ ```
4086
+
4087
+ ``` cpp
4088
+ constexpr explicit sentinel(Parent& parent);
4089
+ ```
4090
+
4091
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
4092
+
4093
+ ``` cpp
4094
+ constexpr sentinel(sentinel<!Const> s)
4095
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4096
+ ```
4097
+
4098
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
4099
+
4100
+ ``` cpp
4101
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
4102
+ ```
4103
+
4104
+ *Effects:* Equivalent to: `return x.`*`outer_`*` == y.`*`end_`*`;`
4105
+
4106
+ ### Split view <a id="range.split">[[range.split]]</a>
4107
+
4108
+ #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
4109
+
4110
+ `split_view` takes a `view` and a delimiter, and splits the `view` into
4111
+ subranges on the delimiter. The delimiter can be a single element or a
4112
+ `view` of elements.
4113
+
4114
+ The name `views::split` denotes a range adaptor object
4115
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
4116
+ expression `views::split(E, F)` is expression-equivalent to
4117
+ `split_view{E, F}`.
4118
+
4119
+ [*Example 1*:
4120
+
4121
+ ``` cpp
4122
+ string str{"the quick brown fox"};
4123
+ split_view sentence{str, ' '};
4124
+ for (auto word : sentence) {
4125
+ for (char ch : word)
4126
+ cout << ch;
4127
+ cout << '*';
4128
+ }
4129
+ // The above prints: the*quick*brown*fox*
4130
+ ```
4131
+
4132
+ — *end example*]
4133
+
4134
+ #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
4135
+
4136
+ ``` cpp
4137
+ namespace std::ranges {
4138
+ template<auto> struct require-constant; // exposition only
4139
+
4140
+ template<class R>
4141
+ concept tiny-range = // exposition only
4142
+ sized_range<R> &&
4143
+ requires { typename require-constant<remove_reference_t<R>::size()>; } &&
4144
+ (remove_reference_t<R>::size() <= 1);
4145
+
4146
+ template<input_range V, forward_range Pattern>
4147
+ requires view<V> && view<Pattern> &&
4148
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4149
+ (forward_range<V> || tiny-range<Pattern>)
4150
+ class split_view : public view_interface<split_view<V, Pattern>> {
4151
+ private:
4152
+ V base_ = V(); // exposition only
4153
+ Pattern pattern_ = Pattern(); // exposition only
4154
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if !forward_range<V>
4155
+ // [range.split.outer], class template split_view::outer-iterator
4156
+ template<bool> struct outer-iterator; // exposition only
4157
+ // [range.split.inner], class template split_view::inner-iterator
4158
+ template<bool> struct inner-iterator; // exposition only
4159
+ public:
4160
+ split_view() = default;
4161
+ constexpr split_view(V base, Pattern pattern);
4162
+
4163
+ template<input_range R>
4164
+ requires constructible_from<V, views::all_t<R>> &&
4165
+ constructible_from<Pattern, single_view<range_value_t<R>>>
4166
+ constexpr split_view(R&& r, range_value_t<R> e);
4167
+
4168
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
4169
+ constexpr V base() && { return std::move(base_); }
4170
+
4171
+ constexpr auto begin() {
4172
+ if constexpr (forward_range<V>)
4173
+ return outer-iterator<simple-view<V>>{*this, ranges::begin(base_)};
4174
+ else {
4175
+ current_ = ranges::begin(base_);
4176
+ return outer-iterator<false>{*this};
4177
+ }
4178
+ }
4179
+
4180
+ constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
4181
+ return outer-iterator<true>{*this, ranges::begin(base_)};
4182
+ }
4183
+
4184
+ constexpr auto end() requires forward_range<V> && common_range<V> {
4185
+ return outer-iterator<simple-view<V>>{*this, ranges::end(base_)};
4186
+ }
4187
+
4188
+ constexpr auto end() const {
4189
+ if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
4190
+ return outer-iterator<true>{*this, ranges::end(base_)};
4191
+ else
4192
+ return default_sentinel;
4193
+ }
4194
+ };
4195
+
4196
+ template<class R, class P>
4197
+ split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
4198
+
4199
+ template<input_range R>
4200
+ split_view(R&&, range_value_t<R>)
4201
+ -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
4202
+ }
4203
+ ```
4204
+
4205
+ ``` cpp
4206
+ constexpr split_view(V base, Pattern pattern);
4207
+ ```
4208
+
4209
+ *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
4210
+ with `std::move(pattern)`.
4211
+
4212
+ ``` cpp
4213
+ template<input_range R>
4214
+ requires constructible_from<V, views::all_t<R>> &&
4215
+ constructible_from<Pattern, single_view<range_value_t<R>>>
4216
+ constexpr split_view(R&& r, range_value_t<R> e);
4217
+ ```
4218
+
4219
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
4220
+ and *pattern\_* with `single_view{std::move(e)}`.
4221
+
4222
+ #### Class template `split_view::outer-iterator` <a id="range.split.outer">[[range.split.outer]]</a>
4223
+
4224
+ ``` cpp
4225
+ namespace std::ranges {
4226
+ template<input_range V, forward_range Pattern>
4227
+ requires view<V> && view<Pattern> &&
4228
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4229
+ (forward_range<V> || tiny-range<Pattern>)
4230
+ template<bool Const>
4231
+ struct split_view<V, Pattern>::outer-iterator {
4232
+ private:
4233
+ using Parent = // exposition only
4234
+ conditional_t<Const, const split_view, split_view>;
4235
+ using Base = // exposition only
4236
+ conditional_t<Const, const V, V>;
4237
+ Parent* parent_ = nullptr; // exposition only
4238
+ iterator_t<Base> current_ = // exposition only, present only if V models forward_range
4239
+ iterator_t<Base>();
4240
+
4241
+ public:
4242
+ using iterator_concept =
4243
+ conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
4244
+ using iterator_category = input_iterator_tag;
4245
+ // [range.split.outer.value], class split_view::outer-iterator::value_type
4246
+ struct value_type;
4247
+ using difference_type = range_difference_t<Base>;
4248
+
4249
+ outer-iterator() = default;
4250
+ constexpr explicit outer-iterator(Parent& parent)
4251
+ requires (!forward_range<Base>);
4252
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
4253
+ requires forward_range<Base>;
4254
+ constexpr outer-iterator(outer-iterator<!Const> i)
4255
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4256
+
4257
+ constexpr value_type operator*() const;
4258
+
4259
+ constexpr outer-iterator& operator++();
4260
+ constexpr decltype(auto) operator++(int) {
4261
+ if constexpr (forward_range<Base>) {
4262
+ auto tmp = *this;
4263
+ ++*this;
4264
+ return tmp;
4265
+ } else
4266
+ ++*this;
4267
+ }
4268
+
4269
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
4270
+ requires forward_range<Base>;
4271
+
4272
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
4273
+ };
4274
+ }
4275
+ ```
4276
+
4277
+ Many of the following specifications refer to the notional member
4278
+ *current* of *`outer-iterator`*. *current* is equivalent to *`current_`*
4279
+ if `V` models `forward_range`, and `parent_->current_` otherwise.
4280
+
4281
+ ``` cpp
4282
+ constexpr explicit outer-iterator(Parent& parent)
4283
+ requires (!forward_range<Base>);
4284
+ ```
4285
+
4286
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
4287
+
4288
+ ``` cpp
4289
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
4290
+ requires forward_range<Base>;
4291
+ ```
4292
+
4293
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and
4294
+ *current\_* with `std::move(current)`.
4295
+
4296
+ ``` cpp
4297
+ constexpr outer-iterator(outer-iterator<!Const> i)
4298
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4299
+ ```
4300
+
4301
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
4302
+ with `std::move(i.`*`current_`*`)`.
4303
+
4304
+ ``` cpp
4305
+ constexpr value_type operator*() const;
4306
+ ```
4307
+
4308
+ *Effects:* Equivalent to: `return value_type{*this};`
4309
+
4310
+ ``` cpp
4311
+ constexpr outer-iterator& operator++();
4312
+ ```
4313
+
4314
+ *Effects:* Equivalent to:
4315
+
4316
+ ``` cpp
4317
+ const auto end = ranges::end(parent_->base_);
4318
+ if (current == end) return *this;
4319
+ const auto [pbegin, pend] = subrange{parent_->pattern_};
4320
+ if (pbegin == pend) ++current;
4321
+ else {
4322
+ do {
4323
+ auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
4324
+ current = std::move(b);
4325
+ if (p == pend) {
4326
+ break; // The pattern matched; skip it
4327
+ }
4328
+ } while (++current != end);
4329
+ }
4330
+ return *this;
4331
+ ```
4332
+
4333
+ ``` cpp
4334
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
4335
+ requires forward_range<Base>;
4336
+ ```
4337
+
4338
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
4339
+
4340
+ ``` cpp
4341
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
4342
+ ```
4343
+
4344
+ *Effects:* Equivalent to:
4345
+ `return x.`*`current`*` == ranges::end(x.`*`parent_`*`->`*`base_`*`);`
4346
+
4347
+ #### Class `split_view::outer-iterator::value_type` <a id="range.split.outer.value">[[range.split.outer.value]]</a>
4348
+
4349
+ ``` cpp
4350
+ namespace std::ranges {
4351
+ template<input_range V, forward_range Pattern>
4352
+ requires view<V> && view<Pattern> &&
4353
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4354
+ (forward_range<V> || tiny-range<Pattern>)
4355
+ template<bool Const>
4356
+ struct split_view<V, Pattern>::outer-iterator<Const>::value_type
4357
+ : view_interface<value_type> {
4358
+ private:
4359
+ outer-iterator i_ = outer-iterator(); // exposition only
4360
+ public:
4361
+ value_type() = default;
4362
+ constexpr explicit value_type(outer-iterator i);
4363
+
4364
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
4365
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
4366
+ constexpr default_sentinel_t end() const;
4367
+ };
4368
+ }
4369
+ ```
4370
+
4371
+ ``` cpp
4372
+ constexpr explicit value_type(outer-iterator i);
4373
+ ```
4374
+
4375
+ *Effects:* Initializes *i\_* with `std::move(i)`.
4376
+
4377
+ ``` cpp
4378
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
4379
+ ```
4380
+
4381
+ *Effects:* Equivalent to:
4382
+ `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
4383
+
4384
+ ``` cpp
4385
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
4386
+ ```
4387
+
4388
+ *Effects:* Equivalent to:
4389
+ `return `*`inner-iterator`*`<Const>{std::move(`*`i_`*`)};`
4390
+
4391
+ ``` cpp
4392
+ constexpr default_sentinel_t end() const;
4393
+ ```
4394
+
4395
+ *Effects:* Equivalent to: `return default_sentinel;`
4396
+
4397
+ #### Class template `split_view::inner-iterator` <a id="range.split.inner">[[range.split.inner]]</a>
4398
+
4399
+ ``` cpp
4400
+ namespace std::ranges {
4401
+ template<input_range V, forward_range Pattern>
4402
+ requires view<V> && view<Pattern> &&
4403
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4404
+ (forward_range<V> || tiny-range<Pattern>)
4405
+ template<bool Const>
4406
+ struct split_view<V, Pattern>::inner-iterator {
4407
+ private:
4408
+ using Base = conditional_t<Const, const V, V>; // exposition only
4409
+ outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
4410
+ bool incremented_ = false; // exposition only
4411
+ public:
4412
+ using iterator_concept = typename outer-iterator<Const>::iterator_concept;
4413
+ using iterator_category = see below;
4414
+ using value_type = range_value_t<Base>;
4415
+ using difference_type = range_difference_t<Base>;
4416
+
4417
+ inner-iterator() = default;
4418
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
4419
+
4420
+ constexpr decltype(auto) operator*() const { return *i_.current; }
4421
+
4422
+ constexpr inner-iterator& operator++();
4423
+ constexpr decltype(auto) operator++(int) {
4424
+ if constexpr (forward_range<V>) {
4425
+ auto tmp = *this;
4426
+ ++*this;
4427
+ return tmp;
4428
+ } else
4429
+ ++*this;
4430
+ }
4431
+
4432
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
4433
+ requires forward_range<Base>;
4434
+
4435
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
4436
+
4437
+ friend constexpr decltype(auto) iter_move(const inner-iterator& i)
4438
+ noexcept(noexcept(ranges::iter_move(i.i_.current))) {
4439
+ return ranges::iter_move(i.i_.current);
4440
+ }
4441
+
4442
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
4443
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
4444
+ requires indirectly_swappable<iterator_t<Base>>;
4445
+ };
4446
+ }
4447
+ ```
4448
+
4449
+ The *typedef-name* `iterator_category` denotes:
4450
+
4451
+ - `forward_iterator_tag` if
4452
+ `iterator_traits<iterator_t<Base>>::iterator_category` models
4453
+ `derived_from<forward_iterator_tag>`;
4454
+ - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
4455
+
4456
+ ``` cpp
4457
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
4458
+ ```
4459
+
4460
+ *Effects:* Initializes *i\_* with `std::move(i)`.
4461
+
4462
+ ``` cpp
4463
+ constexpr inner-iterator& operator++();
4464
+ ```
4465
+
4466
+ *Effects:* Equivalent to:
4467
+
4468
+ ``` cpp
4469
+ incremented_ = true;
4470
+ if constexpr (!forward_range<Base>) {
4471
+ if constexpr (Pattern::size() == 0) {
4472
+ return *this;
4473
+ }
4474
+ }
4475
+ ++i_.current;
4476
+ return *this;
4477
+ ```
4478
+
4479
+ ``` cpp
4480
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
4481
+ requires forward_range<Base>;
4482
+ ```
4483
+
4484
+ *Effects:* Equivalent to:
4485
+ `return x.`*`i_`*`.`*`current`*` == y.`*`i_`*`.`*`current`*`;`
4486
+
4487
+ ``` cpp
4488
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
4489
+ ```
4490
+
4491
+ *Effects:* Equivalent to:
4492
+
4493
+ ``` cpp
4494
+ auto [pcur, pend] = subrange{x.i_.parent_->pattern_};
4495
+ auto end = ranges::end(x.i_.parent_->base_);
4496
+ if constexpr (tiny-range<Pattern>) {
4497
+ const auto & cur = x.i_.current;
4498
+ if (cur == end) return true;
4499
+ if (pcur == pend) return x.incremented_;
4500
+ return *cur == *pcur;
4501
+ } else {
4502
+ auto cur = x.i_.current;
4503
+ if (cur == end) return true;
4504
+ if (pcur == pend) return x.incremented_;
4505
+ do {
4506
+ if (*cur != *pcur) return false;
4507
+ if (++pcur == pend) return true;
4508
+ } while (++cur != end);
4509
+ return false;
4510
+ }
4511
+ ```
4512
+
4513
+ ``` cpp
4514
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
4515
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
4516
+ requires indirectly_swappable<iterator_t<Base>>;
4517
+ ```
4518
+
4519
+ *Effects:* Equivalent to
4520
+ `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
4521
+
4522
+ ### Counted view <a id="range.counted">[[range.counted]]</a>
4523
+
4524
+ A counted view presents a `view` of the elements of the counted range
4525
+ [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
4526
+ non-negative integer `n`.
4527
+
4528
+ The name `views::counted` denotes a customization point object
4529
+ [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
4530
+ be `decay_t<decltype((E))>`, and let `D` be `iter_difference_t<T>`. If
4531
+ `decltype((F))` does not model `convertible_to<D>`,
4532
+ `views::counted(E, F)` is ill-formed.
4533
+
4534
+ [*Note 1*: This case can result in substitution failure when
4535
+ `views::counted(E, F)` appears in the immediate context of a template
4536
+ instantiation. — *end note*]
4537
+
4538
+ Otherwise, `views::counted(E, F)` is expression-equivalent to:
4539
+
4540
+ - If `T` models `contiguous_iterator`, then
4541
+ `span{to_address(E), static_cast<D>(F)}`.
4542
+ - Otherwise, if `T` models `random_access_iterator`, then
4543
+ `subrange{E, E + static_cast<D>(F)}`, except that `E` is evaluated
4544
+ only once.
4545
+ - Otherwise, `subrange{counted_iterator{E, F}, default_sentinel}`.
4546
+
4547
+ ### Common view <a id="range.common">[[range.common]]</a>
4548
+
4549
+ #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
4550
+
4551
+ `common_view` takes a `view` which has different types for its iterator
4552
+ and sentinel and turns it into a `view` of the same elements with an
4553
+ iterator and sentinel of the same type.
4554
+
4555
+ [*Note 1*: `common_view` is useful for calling legacy algorithms that
4556
+ expect a range’s iterator and sentinel types to be the
4557
+ same. — *end note*]
4558
+
4559
+ The name `views::common` denotes a range adaptor object
4560
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
4561
+ `views::common(E)` is expression-equivalent to:
4562
+
4563
+ - `views::all(E)`, if `decltype((E))` models `common_range` and
4564
+ `views::all(E)` is a well-formed expression.
4565
+ - Otherwise, `common_view{E}`.
4566
+
4567
+ [*Example 1*:
4568
+
4569
+ ``` cpp
4570
+ // Legacy algorithm:
4571
+ template<class ForwardIterator>
4572
+ size_t count(ForwardIterator first, ForwardIterator last);
4573
+
4574
+ template<forward_range R>
4575
+ void my_algo(R&& r) {
4576
+ auto&& common = common_view{r};
4577
+ auto cnt = count(common.begin(), common.end());
4578
+ // ...
4579
+ }
4580
+ ```
4581
+
4582
+ — *end example*]
4583
+
4584
+ #### Class template `common_view` <a id="range.common.view">[[range.common.view]]</a>
4585
+
4586
+ ``` cpp
4587
+ namespace std::ranges {
4588
+ template<view V>
4589
+ requires (!common_range<V> && copyable<iterator_t<V>>)
4590
+ class common_view : public view_interface<common_view<V>> {
4591
+ private:
4592
+ V base_ = V(); // exposition only
4593
+ public:
4594
+ common_view() = default;
4595
+
4596
+ constexpr explicit common_view(V r);
4597
+
4598
+ template<viewable_range R>
4599
+ requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
4600
+ constexpr explicit common_view(R&& r);
4601
+
4602
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
4603
+ constexpr V base() && { return std::move(base_); }
4604
+
4605
+ constexpr auto begin() {
4606
+ if constexpr (random_access_range<V> && sized_range<V>)
4607
+ return ranges::begin(base_);
4608
+ else
4609
+ return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
4610
+ }
4611
+
4612
+ constexpr auto begin() const requires range<const V> {
4613
+ if constexpr (random_access_range<const V> && sized_range<const V>)
4614
+ return ranges::begin(base_);
4615
+ else
4616
+ return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
4617
+ }
4618
+
4619
+ constexpr auto end() {
4620
+ if constexpr (random_access_range<V> && sized_range<V>)
4621
+ return ranges::begin(base_) + ranges::size(base_);
4622
+ else
4623
+ return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
4624
+ }
4625
+
4626
+ constexpr auto end() const requires range<const V> {
4627
+ if constexpr (random_access_range<const V> && sized_range<const V>)
4628
+ return ranges::begin(base_) + ranges::size(base_);
4629
+ else
4630
+ return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
4631
+ }
4632
+
4633
+ constexpr auto size() requires sized_range<V> {
4634
+ return ranges::size(base_);
4635
+ }
4636
+ constexpr auto size() const requires sized_range<const V> {
4637
+ return ranges::size(base_);
4638
+ }
4639
+ };
4640
+
4641
+ template<class R>
4642
+ common_view(R&&) -> common_view<views::all_t<R>>;
4643
+ }
4644
+ ```
4645
+
4646
+ ``` cpp
4647
+ constexpr explicit common_view(V base);
4648
+ ```
4649
+
4650
+ *Effects:* Initializes *base\_* with `std::move(base)`.
4651
+
4652
+ ``` cpp
4653
+ template<viewable_range R>
4654
+ requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
4655
+ constexpr explicit common_view(R&& r);
4656
+ ```
4657
+
4658
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`.
4659
+
4660
+ ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
4661
+
4662
+ #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
4663
+
4664
+ `reverse_view` takes a bidirectional `view` and produces another `view`
4665
+ that iterates the same elements in reverse order.
4666
+
4667
+ The name `views::reverse` denotes a range adaptor object
4668
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
4669
+ `views::reverse(E)` is expression-equivalent to:
4670
+
4671
+ - If the type of `E` is a (possibly cv-qualified) specialization of
4672
+ `reverse_view`, equivalent to `E.base()`.
4673
+ - Otherwise, if the type of `E` is cv-qualified
4674
+ ``` cpp
4675
+ subrange<reverse_iterator<I>, reverse_iterator<I>, K>
4676
+ ```
4677
+
4678
+ for some iterator type `I` and value `K` of type `subrange_kind`,
4679
+ - if `K` is `subrange_kind::sized`, equivalent to:
4680
+ ``` cpp
4681
+ subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
4682
+ ```
4683
+ - otherwise, equivalent to:
4684
+ ``` cpp
4685
+ subrange<I, I, K>(E.end().base(), E.begin().base())
4686
+ ```
4687
+
4688
+ However, in either case `E` is evaluated only once.
4689
+ - Otherwise, equivalent to `reverse_view{E}`.
4690
+
4691
+ [*Example 1*:
4692
+
4693
+ ``` cpp
4694
+ vector<int> is {0,1,2,3,4};
4695
+ reverse_view rv {is};
4696
+ for (int i : rv)
4697
+ cout << i << ' '; // prints: 4 3 2 1 0
4698
+ ```
4699
+
4700
+ — *end example*]
4701
+
4702
+ #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
4703
+
4704
+ ``` cpp
4705
+ namespace std::ranges {
4706
+ template<view V>
4707
+ requires bidirectional_range<V>
4708
+ class reverse_view : public view_interface<reverse_view<V>> {
4709
+ private:
4710
+ V base_ = V(); // exposition only
4711
+ public:
4712
+ reverse_view() = default;
4713
+
4714
+ constexpr explicit reverse_view(V r);
4715
+
4716
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
4717
+ constexpr V base() && { return std::move(base_); }
4718
+
4719
+ constexpr reverse_iterator<iterator_t<V>> begin();
4720
+ constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
4721
+ constexpr auto begin() const requires common_range<const V>;
4722
+
4723
+ constexpr reverse_iterator<iterator_t<V>> end();
4724
+ constexpr auto end() const requires common_range<const V>;
4725
+
4726
+ constexpr auto size() requires sized_range<V> {
4727
+ return ranges::size(base_);
4728
+ }
4729
+ constexpr auto size() const requires sized_range<const V> {
4730
+ return ranges::size(base_);
4731
+ }
4732
+ };
4733
+
4734
+ template<class R>
4735
+ reverse_view(R&&) -> reverse_view<views::all_t<R>>;
4736
+ }
4737
+ ```
4738
+
4739
+ ``` cpp
4740
+ constexpr explicit reverse_view(V base);
4741
+ ```
4742
+
4743
+ *Effects:* Initializes *base\_* with `std::move(base)`.
4744
+
4745
+ ``` cpp
4746
+ constexpr reverse_iterator<iterator_t<V>> begin();
4747
+ ```
4748
+
4749
+ *Returns:*
4750
+
4751
+ ``` cpp
4752
+ make_reverse_iterator(ranges::next(ranges::begin(base_), ranges::end(base_)))
4753
+ ```
4754
+
4755
+ *Remarks:* In order to provide the amortized constant time complexity
4756
+ required by the `range` concept, this function caches the result within
4757
+ the `reverse_view` for use on subsequent calls.
4758
+
4759
+ ``` cpp
4760
+ constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
4761
+ constexpr auto begin() const requires common_range<const V>;
4762
+ ```
4763
+
4764
+ *Effects:* Equivalent to:
4765
+ `return make_reverse_iterator(ranges::end(base_));`
4766
+
4767
+ ``` cpp
4768
+ constexpr reverse_iterator<iterator_t<V>> end();
4769
+ constexpr auto end() const requires common_range<const V>;
4770
+ ```
4771
+
4772
+ *Effects:* Equivalent to:
4773
+ `return make_reverse_iterator(ranges::begin(base_));`
4774
+
4775
+ ### Elements view <a id="range.elements">[[range.elements]]</a>
4776
+
4777
+ #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
4778
+
4779
+ `elements_view` takes a `view` of tuple-like values and a `size_t`, and
4780
+ produces a `view` with a value-type of the Nᵗʰ element of the adapted
4781
+ `view`’s value-type.
4782
+
4783
+ The name `views::elements<N>` denotes a range adaptor object
4784
+ [[range.adaptor.object]]. Given a subexpression `E` and constant
4785
+ expression `N`, the expression `views::elements<N>(E)` is
4786
+ expression-equivalent to
4787
+ `elements_view<views::all_t<decltype((E))>, N>{E}`.
4788
+
4789
+ [*Example 1*:
4790
+
4791
+ ``` cpp
4792
+ auto historical_figures = map{
4793
+ {"Lovelace"sv, 1815},
4794
+ {"Turing"sv, 1912},
4795
+ {"Babbage"sv, 1791},
4796
+ {"Hamilton"sv, 1936}
4797
+ };
4798
+
4799
+ auto names = historical_figures | views::elements<0>;
4800
+ for (auto&& name : names) {
4801
+ cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
4802
+ }
4803
+
4804
+ auto birth_years = historical_figures | views::elements<1>;
4805
+ for (auto&& born : birth_years) {
4806
+ cout << born << ' '; // prints 1791 1936 1815 1912
4807
+ }
4808
+ ```
4809
+
4810
+ — *end example*]
4811
+
4812
+ `keys_view` is an alias for `elements_view<views::all_t<R>, 0>`, and is
4813
+ useful for extracting keys from associative containers.
4814
+
4815
+ [*Example 2*:
4816
+
4817
+ ``` cpp
4818
+ auto names = keys_view{historical_figures};
4819
+ for (auto&& name : names) {
4820
+ cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
4821
+ }
4822
+ ```
4823
+
4824
+ — *end example*]
4825
+
4826
+ `values_view` is an alias for `elements_view<views::all_t<R>, 1>`, and
4827
+ is useful for extracting values from associative containers.
4828
+
4829
+ [*Example 3*:
4830
+
4831
+ ``` cpp
4832
+ auto is_even = [](const auto x) { return x % 2 == 0; };
4833
+ cout << ranges::count_if(values_view{historical_figures}, is_even); // prints 2
4834
+ ```
4835
+
4836
+ — *end example*]
4837
+
4838
+ #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
4839
+
4840
+ ``` cpp
4841
+ namespace std::ranges {
4842
+ template<class T, size_t N>
4843
+ concept has-tuple-element = // exposition only
4844
+ requires(T t) {
4845
+ typename tuple_size<T>::type;
4846
+ requires N < tuple_size_v<T>;
4847
+ typename tuple_element_t<N, T>;
4848
+ { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
4849
+ };
4850
+
4851
+
4852
+ template<input_range V, size_t N>
4853
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
4854
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
4855
+ class elements_view : public view_interface<elements_view<V, N>> {
4856
+ public:
4857
+ elements_view() = default;
4858
+ constexpr explicit elements_view(V base);
4859
+
4860
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
4861
+ constexpr V base() && { return std::move(base_); }
4862
+
4863
+ constexpr auto begin() requires (!simple-view<V>)
4864
+ { return iterator<false>(ranges::begin(base_)); }
4865
+
4866
+ constexpr auto begin() const requires simple-view<V>
4867
+ { return iterator<true>(ranges::begin(base_)); }
4868
+
4869
+ constexpr auto end()
4870
+ { return sentinel<false>{ranges::end(base_)}; }
4871
+
4872
+ constexpr auto end() requires common_range<V>
4873
+ { return iterator<false>{ranges::end(base_)}; }
4874
+
4875
+ constexpr auto end() const requires range<const V>
4876
+ { return sentinel<true>{ranges::end(base_)}; }
4877
+
4878
+ constexpr auto end() const requires common_range<const V>
4879
+ { return iterator<true>{ranges::end(base_)}; }
4880
+
4881
+ constexpr auto size() requires sized_range<V>
4882
+ { return ranges::size(base_); }
4883
+
4884
+ constexpr auto size() const requires sized_range<const V>
4885
+ { return ranges::size(base_); }
4886
+
4887
+ private:
4888
+ // [range.elements.iterator], class template elements_view::iterator
4889
+ template<bool> struct iterator; // exposition only
4890
+ // [range.elements.sentinel], class template elements_view::sentinel
4891
+ template<bool> struct sentinel; // exposition only
4892
+ V base_ = V(); // exposition only
4893
+ };
4894
+ }
4895
+ ```
4896
+
4897
+ ``` cpp
4898
+ constexpr explicit elements_view(V base);
4899
+ ```
4900
+
4901
+ *Effects:* Initializes *base\_* with `std::move(base)`.
4902
+
4903
+ #### Class template `elements_view::iterator` <a id="range.elements.iterator">[[range.elements.iterator]]</a>
4904
+
4905
+ ``` cpp
4906
+ namespace std::ranges {
4907
+ template<input_range V, size_t N>
4908
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
4909
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
4910
+ template<bool Const>
4911
+ class elements_view<V, N>::iterator { // exposition only
4912
+ using Base = conditional_t<Const, const V, V>; // exposition only
4913
+
4914
+ iterator_t<Base> current_ = iterator_t<Base>();
4915
+ public:
4916
+ using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
4917
+ using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
4918
+ using difference_type = range_difference_t<Base>;
4919
+
4920
+ iterator() = default;
4921
+ constexpr explicit iterator(iterator_t<Base> current);
4922
+ constexpr iterator(iterator<!Const> i)
4923
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4924
+
4925
+ constexpr iterator_t<Base> base() const&
4926
+ requires copyable<iterator_t<Base>>;
4927
+ constexpr iterator_t<Base> base() &&;
4928
+
4929
+ constexpr decltype(auto) operator*() const
4930
+ { return get<N>(*current_); }
4931
+
4932
+ constexpr iterator& operator++();
4933
+ constexpr void operator++(int) requires (!forward_range<Base>);
4934
+ constexpr iterator operator++(int) requires forward_range<Base>;
4935
+
4936
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
4937
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
4938
+
4939
+ constexpr iterator& operator+=(difference_type x)
4940
+ requires random_access_range<Base>;
4941
+ constexpr iterator& operator-=(difference_type x)
4942
+ requires random_access_range<Base>;
4943
+
4944
+ constexpr decltype(auto) operator[](difference_type n) const
4945
+ requires random_access_range<Base>
4946
+ { return get<N>(*(current_ + n)); }
4947
+
4948
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
4949
+ requires equality_comparable<iterator_t<Base>>;
4950
+
4951
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
4952
+ requires random_access_range<Base>;
4953
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
4954
+ requires random_access_range<Base>;
4955
+ friend constexpr bool operator<=(const iterator& y, const iterator& y)
4956
+ requires random_access_range<Base>;
4957
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
4958
+ requires random_access_range<Base>;
4959
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
4960
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
4961
+
4962
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
4963
+ requires random_access_range<Base>;
4964
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
4965
+ requires random_access_range<Base>;
4966
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
4967
+ requires random_access_range<Base>;
4968
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4969
+ requires random_access_range<Base>;
4970
+ };
4971
+ }
4972
+ ```
4973
+
4974
+ ``` cpp
4975
+ constexpr explicit iterator(iterator_t<Base> current);
4976
+ ```
4977
+
4978
+ *Effects:* Initializes *current\_* with `std::move(current)`.
4979
+
4980
+ ``` cpp
4981
+ constexpr iterator(iterator<!Const> i)
4982
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4983
+ ```
4984
+
4985
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
4986
+
4987
+ ``` cpp
4988
+ constexpr iterator_t<Base> base() const&
4989
+ requires copyable<iterator_t<Base>>;
4990
+ ```
4991
+
4992
+ *Effects:* Equivalent to: `return `*`current_`*`;`
4993
+
4994
+ ``` cpp
4995
+ constexpr iterator_t<Base> base() &&;
4996
+ ```
4997
+
4998
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
4999
+
5000
+ ``` cpp
5001
+ constexpr iterator& operator++();
5002
+ ```
5003
+
5004
+ *Effects:* Equivalent to:
5005
+
5006
+ ``` cpp
5007
+ ++current_;
5008
+ return *this;
5009
+ ```
5010
+
5011
+ ``` cpp
5012
+ constexpr void operator++(int) requires (!forward_range<Base>);
5013
+ ```
5014
+
5015
+ *Effects:* Equivalent to: `++`*`current_`*.
5016
+
5017
+ ``` cpp
5018
+ constexpr iterator operator++(int) requires forward_range<Base>;
5019
+ ```
5020
+
5021
+ *Effects:* Equivalent to:
5022
+
5023
+ ``` cpp
5024
+ auto temp = *this;
5025
+ ++current_;
5026
+ return temp;
5027
+ ```
5028
+
5029
+ ``` cpp
5030
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
5031
+ ```
5032
+
5033
+ *Effects:* Equivalent to:
5034
+
5035
+ ``` cpp
5036
+ --current_;
5037
+ return *this;
5038
+ ```
5039
+
5040
+ ``` cpp
5041
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
5042
+ ```
5043
+
5044
+ *Effects:* Equivalent to:
5045
+
5046
+ ``` cpp
5047
+ auto temp = *this;
5048
+ --current_;
5049
+ return temp;
5050
+ ```
5051
+
5052
+ ``` cpp
5053
+ constexpr iterator& operator+=(difference_type n);
5054
+ requires random_access_range<Base>;
5055
+ ```
5056
+
5057
+ *Effects:* Equivalent to:
5058
+
5059
+ ``` cpp
5060
+ current_ += n;
5061
+ return *this;
5062
+ ```
5063
+
5064
+ ``` cpp
5065
+ constexpr iterator& operator-=(difference_type n)
5066
+ requires random_access_range<Base>;
5067
+ ```
5068
+
5069
+ *Effects:* Equivalent to:
5070
+
5071
+ ``` cpp
5072
+ current_ -= n;
5073
+ return *this;
5074
+ ```
5075
+
5076
+ ``` cpp
5077
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5078
+ requires equality_comparable<Base>;
5079
+ ```
5080
+
5081
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
5082
+
5083
+ ``` cpp
5084
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
5085
+ requires random_access_range<Base>;
5086
+ ```
5087
+
5088
+ *Effects:* Equivalent to: `return x.`*`current_`*` < y.`*`current_`*`;`
5089
+
5090
+ ``` cpp
5091
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
5092
+ requires random_access_range<Base>;
5093
+ ```
5094
+
5095
+ *Effects:* Equivalent to: `return y < x;`
5096
+
5097
+ ``` cpp
5098
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
5099
+ requires random_access_range<Base>;
5100
+ ```
5101
+
5102
+ *Effects:* Equivalent to: `return !(y < x);`
5103
+
5104
+ ``` cpp
5105
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
5106
+ requires random_access_range<Base>;
5107
+ ```
5108
+
5109
+ *Effects:* Equivalent to: `return !(x < y);`
5110
+
5111
+ ``` cpp
5112
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5113
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
5114
+ ```
5115
+
5116
+ *Effects:* Equivalent to:
5117
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
5118
+
5119
+ ``` cpp
5120
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
5121
+ requires random_access_range<Base>;
5122
+ ```
5123
+
5124
+ *Effects:* Equivalent to: `return iterator{x} += y;`
5125
+
5126
+ ``` cpp
5127
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
5128
+ requires random_access_range<Base>;
5129
+ ```
5130
+
5131
+ *Effects:* Equivalent to: `return y + x;`
5132
+
5133
+ ``` cpp
5134
+ constexpr iterator operator-(const iterator& x, difference_type y)
5135
+ requires random_access_range<Base>;
5136
+ ```
5137
+
5138
+ *Effects:* Equivalent to: `return iterator{x} -= y;`
5139
+
5140
+ ``` cpp
5141
+ constexpr difference_type operator-(const iterator& x, const iterator& y)
5142
+ requires random_access_range<Base>;
5143
+ ```
5144
+
5145
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
5146
+
5147
+ #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
5148
+
5149
+ ``` cpp
5150
+ namespace std::ranges {
5151
+ template<input_range V, size_t N>
5152
+ requires view<V> && has-tuple-element<range_value_t<V>, N> &&
5153
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
5154
+ template<bool Const>
5155
+ class elements_view<V, N>::sentinel { // exposition only
5156
+ private:
5157
+ using Base = conditional_t<Const, const V, V>; // exposition only
5158
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
5159
+ public:
5160
+ sentinel() = default;
5161
+ constexpr explicit sentinel(sentinel_t<Base> end);
5162
+ constexpr sentinel(sentinel<!Const> other)
5163
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5164
+
5165
+ constexpr sentinel_t<Base> base() const;
5166
+
5167
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
5168
+
5169
+ friend constexpr range_difference_t<Base>
5170
+ operator-(const iterator<Const>& x, const sentinel& y)
5171
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
5172
+
5173
+ friend constexpr range_difference_t<Base>
5174
+ operator-(const sentinel& x, const iterator<Const>& y)
5175
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
5176
+ };
5177
+ }
5178
+ ```
5179
+
5180
+ ``` cpp
5181
+ constexpr explicit sentinel(sentinel_t<Base> end);
5182
+ ```
5183
+
5184
+ *Effects:* Initializes *end\_* with `end`.
5185
+
5186
+ ``` cpp
5187
+ constexpr sentinel(sentinel<!Const> other)
5188
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5189
+ ```
5190
+
5191
+ *Effects:* Initializes *end\_* with `std::move(other.`*`end_`*`)`.
5192
+
5193
+ ``` cpp
5194
+ constexpr sentinel_t<Base> base() const;
5195
+ ```
5196
+
5197
+ *Effects:* Equivalent to: `return `*`end_`*`;`
5198
+
5199
+ ``` cpp
5200
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
5201
+ ```
5202
+
5203
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
5204
+
5205
+ ``` cpp
5206
+ friend constexpr range_difference_t<Base>
5207
+ operator-(const iterator<Const>& x, const sentinel& y)
5208
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
5209
+ ```
5210
+
5211
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
5212
+
5213
+ ``` cpp
5214
+ friend constexpr range_difference_t<Base>
5215
+ operator-(const sentinel& x, const iterator<Const>& y)
5216
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
5217
+ ```
5218
+
5219
+ *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
5220
+
5221
+ <!-- Link reference definitions -->
5222
+ [basic.compound]: basic.md#basic.compound
5223
+ [concepts.equality]: concepts.md#concepts.equality
5224
+ [containers]: containers.md#containers
5225
+ [conv.rval]: expr.md#conv.rval
5226
+ [customization.point.object]: library.md#customization.point.object
5227
+ [dcl.array]: dcl.md#dcl.array
5228
+ [expr.const]: expr.md#expr.const
5229
+ [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
5230
+ [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
5231
+ [iterator.concept.output]: iterators.md#iterator.concept.output
5232
+ [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
5233
+ [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
5234
+ [iterator.concept.winc]: iterators.md#iterator.concept.winc
5235
+ [iterator.requirements.general]: iterators.md#iterator.requirements.general
5236
+ [namespace.std]: library.md#namespace.std
5237
+ [range.access]: #range.access
5238
+ [range.access.begin]: #range.access.begin
5239
+ [range.access.cbegin]: #range.access.cbegin
5240
+ [range.access.cend]: #range.access.cend
5241
+ [range.access.crbegin]: #range.access.crbegin
5242
+ [range.access.crend]: #range.access.crend
5243
+ [range.access.end]: #range.access.end
5244
+ [range.access.rbegin]: #range.access.rbegin
5245
+ [range.access.rend]: #range.access.rend
5246
+ [range.adaptor.object]: #range.adaptor.object
5247
+ [range.adaptors]: #range.adaptors
5248
+ [range.all]: #range.all
5249
+ [range.common]: #range.common
5250
+ [range.common.overview]: #range.common.overview
5251
+ [range.common.view]: #range.common.view
5252
+ [range.counted]: #range.counted
5253
+ [range.dangling]: #range.dangling
5254
+ [range.drop]: #range.drop
5255
+ [range.drop.overview]: #range.drop.overview
5256
+ [range.drop.view]: #range.drop.view
5257
+ [range.drop.while]: #range.drop.while
5258
+ [range.drop.while.overview]: #range.drop.while.overview
5259
+ [range.drop.while.view]: #range.drop.while.view
5260
+ [range.elements]: #range.elements
5261
+ [range.elements.iterator]: #range.elements.iterator
5262
+ [range.elements.overview]: #range.elements.overview
5263
+ [range.elements.sentinel]: #range.elements.sentinel
5264
+ [range.elements.view]: #range.elements.view
5265
+ [range.empty]: #range.empty
5266
+ [range.empty.overview]: #range.empty.overview
5267
+ [range.empty.view]: #range.empty.view
5268
+ [range.factories]: #range.factories
5269
+ [range.filter]: #range.filter
5270
+ [range.filter.iterator]: #range.filter.iterator
5271
+ [range.filter.overview]: #range.filter.overview
5272
+ [range.filter.sentinel]: #range.filter.sentinel
5273
+ [range.filter.view]: #range.filter.view
5274
+ [range.iota]: #range.iota
5275
+ [range.iota.iterator]: #range.iota.iterator
5276
+ [range.iota.overview]: #range.iota.overview
5277
+ [range.iota.sentinel]: #range.iota.sentinel
5278
+ [range.iota.view]: #range.iota.view
5279
+ [range.istream]: #range.istream
5280
+ [range.istream.iterator]: #range.istream.iterator
5281
+ [range.istream.overview]: #range.istream.overview
5282
+ [range.istream.view]: #range.istream.view
5283
+ [range.join]: #range.join
5284
+ [range.join.iterator]: #range.join.iterator
5285
+ [range.join.overview]: #range.join.overview
5286
+ [range.join.sentinel]: #range.join.sentinel
5287
+ [range.join.view]: #range.join.view
5288
+ [range.prim.cdata]: #range.prim.cdata
5289
+ [range.prim.data]: #range.prim.data
5290
+ [range.prim.empty]: #range.prim.empty
5291
+ [range.prim.size]: #range.prim.size
5292
+ [range.prim.ssize]: #range.prim.ssize
5293
+ [range.range]: #range.range
5294
+ [range.ref.view]: #range.ref.view
5295
+ [range.refinements]: #range.refinements
5296
+ [range.req]: #range.req
5297
+ [range.req.general]: #range.req.general
5298
+ [range.reverse]: #range.reverse
5299
+ [range.reverse.overview]: #range.reverse.overview
5300
+ [range.reverse.view]: #range.reverse.view
5301
+ [range.semi.wrap]: #range.semi.wrap
5302
+ [range.single]: #range.single
5303
+ [range.single.overview]: #range.single.overview
5304
+ [range.single.view]: #range.single.view
5305
+ [range.sized]: #range.sized
5306
+ [range.split]: #range.split
5307
+ [range.split.inner]: #range.split.inner
5308
+ [range.split.outer]: #range.split.outer
5309
+ [range.split.outer.value]: #range.split.outer.value
5310
+ [range.split.overview]: #range.split.overview
5311
+ [range.split.view]: #range.split.view
5312
+ [range.subrange]: #range.subrange
5313
+ [range.subrange.access]: #range.subrange.access
5314
+ [range.subrange.ctor]: #range.subrange.ctor
5315
+ [range.summary]: #range.summary
5316
+ [range.take]: #range.take
5317
+ [range.take.overview]: #range.take.overview
5318
+ [range.take.sentinel]: #range.take.sentinel
5319
+ [range.take.view]: #range.take.view
5320
+ [range.take.while]: #range.take.while
5321
+ [range.take.while.overview]: #range.take.while.overview
5322
+ [range.take.while.sentinel]: #range.take.while.sentinel
5323
+ [range.take.while.view]: #range.take.while.view
5324
+ [range.transform]: #range.transform
5325
+ [range.transform.iterator]: #range.transform.iterator
5326
+ [range.transform.overview]: #range.transform.overview
5327
+ [range.transform.sentinel]: #range.transform.sentinel
5328
+ [range.transform.view]: #range.transform.view
5329
+ [range.utility]: #range.utility
5330
+ [range.utility.helpers]: #range.utility.helpers
5331
+ [range.view]: #range.view
5332
+ [ranges]: #ranges
5333
+ [ranges.general]: #ranges.general
5334
+ [ranges.syn]: #ranges.syn
5335
+ [string.view]: strings.md#string.view
5336
+ [view.interface]: #view.interface
5337
+ [view.interface.members]: #view.interface.members
5338
+ [views.span]: containers.md#views.span