iterators must go - accu...warning sign #4 c 2009 andrei alexandrescu 20 / 52 • iterators use...

66
c 2009 Andrei Alexandrescu 1 / 52 Iterators Must Go Andrei Alexandrescu

Upload: others

Post on 16-Jan-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 1 / 52

Iterators Must Go

Andrei Alexandrescu

Page 2: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

This Talk

c© 2009 Andrei Alexandrescu 2 / 52

• The STL

• Iterators

• Range-based design

• Conclusions

Page 3: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

What is the STL?

c© 2009 Andrei Alexandrescu 3 / 52

Page 4: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Yeah, what is the STL?

c© 2009 Andrei Alexandrescu 4 / 52

• A good library of algorithms and data structures.

Page 5: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Yeah, what is the STL?

c© 2009 Andrei Alexandrescu 4 / 52

• A ( good|bad) library of algorithms and data structures.

Page 6: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Yeah, what is the STL?

c© 2009 Andrei Alexandrescu 4 / 52

• A ( good|bad|ugly) library of algorithms and datastructures.

Page 7: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Yeah, what is the STL?

c© 2009 Andrei Alexandrescu 4 / 52

• A ( good|bad|ugly) library of algorithms and datastructures.

• iterators = gcd(containers, algorithms);

Page 8: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Yeah, what is the STL?

c© 2009 Andrei Alexandrescu 4 / 52

• A ( good|bad|ugly) library of algorithms and datastructures.

• iterators = gcd(containers, algorithms);

• Scrumptious Template Lore

• Snout to Tail Length

Page 9: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

What the STL is

c© 2009 Andrei Alexandrescu 5 / 52

• More than the answer, the question is important in theSTL

• “What would the most general implementations offundamental containers and algorithms look like?”

• Everything else is aftermath

• Most importantly: STL is one answer, not the answer

Page 10: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL is nonintuitive

c© 2009 Andrei Alexandrescu 6 / 52

Page 11: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL is nonintuitive

c© 2009 Andrei Alexandrescu 6 / 52

• Same way the theory of relativity is nonintuitive

• Same way complex numbers are nonintuitive (seee.g. xkcd.com)

Page 12: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Nonintuitive

c© 2009 Andrei Alexandrescu 7 / 52

• “I want to design the most general algorithms.”

• “Sure. What you obviously need is something callediterators. Five of ’em, to be precise.”

Page 13: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Nonintuitive

c© 2009 Andrei Alexandrescu 7 / 52

• “I want to design the most general algorithms.”

• “Sure. What you obviously need is something callediterators. Five of ’em, to be precise.”

• Evidence: No language has supported the STL “bychance.”

◦ In spite of relentless “feature wars”

◦ C++, D the only ones

◦ Both were actively designed to support the STL

• Consequence: STL very hard to understand fromoutside C++ or D

Page 14: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Fundamental vs. Incidental in STL

c© 2009 Andrei Alexandrescu 8 / 52

• Algorithms defined for the narrowest interfacepossible

• Broad iterator categories as required by algorithms

• Choice of iterator primitives

• Syntax of iterator primitives

Page 15: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Fundamental vs. Incidental in STL

c© 2009 Andrei Alexandrescu 8 / 52

• F: Algorithms defined for the narrowest interfacepossible

• Broad iterator categories as required by algorithms

• Choice of iterator primitives

• Syntax of iterator primitives

Page 16: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Fundamental vs. Incidental in STL

c© 2009 Andrei Alexandrescu 8 / 52

• F: Algorithms defined for the narrowest interfacepossible

• F: Broad iterator categories as required by algorithms

• Choice of iterator primitives

• Syntax of iterator primitives

Page 17: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Fundamental vs. Incidental in STL

c© 2009 Andrei Alexandrescu 8 / 52

• F: Algorithms defined for the narrowest interfacepossible

• F: Broad iterator categories as required by algorithms

• I: Choice of iterator primitives

• Syntax of iterator primitives

Page 18: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Fundamental vs. Incidental in STL

c© 2009 Andrei Alexandrescu 8 / 52

• F: Algorithms defined for the narrowest interfacepossible

• F: Broad iterator categories as required by algorithms

• I: Choice of iterator primitives

• I: Syntax of iterator primitives

Page 19: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL: The Good

c© 2009 Andrei Alexandrescu 9 / 52

• Asked the right question

• General

• Efficient

• Reasonably extensible

• Integrated with built-in types

Page 20: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL: The Bad

c© 2009 Andrei Alexandrescu 10 / 52

• Poor lambda functions support

Not an STL problem

High opportunity cost

• Some containers cannot be supported

E.g. sentinel-terminated containers

E.g. containers with distributed storage

• Some iteration methods cannot be supported

Page 21: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL: The Ugly

c© 2009 Andrei Alexandrescu 11 / 52

• Attempts at for_each et al. didn’t help

• Integration with streams is tenuous

• One word: allocator

Page 22: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

STL: The Ugly

c© 2009 Andrei Alexandrescu 11 / 52

• Attempts at for_each et al. didn’t help

• Integration with streams is tenuous

• One word: allocator

• Iterators suck

◦ Verbose

◦ Unsafe

◦ Poor Interface

Page 23: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

What’s the Deal with Iterators?

c© 2009 Andrei Alexandrescu 12 / 52

Page 24: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Iterators Rock

c© 2009 Andrei Alexandrescu 13 / 52

• They broker interaction between containers andalgorithms

• “Strength reduction:” m + n implementations instead ofm · n

• Extensible: there’s been a flurry of iterators ever sinceSTL saw the light of day

Page 25: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #1

c© 2009 Andrei Alexandrescu 14 / 52

• C++ Users Journal around 2001 ran an ad campaign

“Submit an article to CUJ!”

“No need to be an English major! Just start youreditor!”

“We’re interested in security, networking, C++techniques, and more!”

Page 26: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #1

c© 2009 Andrei Alexandrescu 14 / 52

• C++ Users Journal around 2001 ran an ad campaign

“Submit an article to CUJ!”

“No need to be an English major! Just start youreditor!”

“We’re interested in security, networking, C++techniques, and more!”

“Please note: Not interested in yet another iterator”

• How many of those published iterators survived?

Page 27: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #2

c© 2009 Andrei Alexandrescu 15 / 52

File copy circa 1975:

#include <stdio.h>

int main() {

int c;

while ((c = getchar()) != EOF)

putchar(c);

return errno != 0;

}

Page 28: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #2

c© 2009 Andrei Alexandrescu 16 / 52

Fast forward 20 years, and. . .

#include <iostream>

#include <algorithm>

#include <iterator>

#include <string>

using namespace std;

int main() {

copy(istream_iterator<string>(cin),

istream_iterator<string>(),

ostream_iterator<string>(cout,"\n"));

}

Page 29: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 17 / 52

(forgot the try/catch around main)

Page 30: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 18 / 52

Something, somewhere, went terribly wrong.

Page 31: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #3

c© 2009 Andrei Alexandrescu 19 / 52

• Iterators are brutally hard to define

• Bulky implementations and many gotchas

• Boost includes an entire library that helps definingiterators

• The essential primitives are like. . . three?

◦ At end◦ Access◦ Bump

Page 32: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Warning Sign #4

c© 2009 Andrei Alexandrescu 20 / 52

• Iterators use pointer syntax & semantics

• Integration with pointers for the win/loss

• However, this limits methods of iteration

◦ Can’t walk a tree in depth, need ++ with aparameter

◦ Output iterators can only accept one type:ostream_iterator must be parameterized witheach specific type to output, although they all go tothe same place

Page 33: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Final nail in the coffin

c© 2009 Andrei Alexandrescu 21 / 52

• All iterator primitives are fundamentally unsafe

• For most iterator types, given an iterator

◦ Can’t say whether it can be compared

◦ Can’t say whether it can be incremented

◦ Can’t say whether it can be dereferenced

• Safe iterators can and have been written

◦ At a high size+speed cost

◦ Mostly a good argument that the design hasn’tbeen cut quite right

Page 34: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Ranges

c© 2009 Andrei Alexandrescu 22 / 52

Page 35: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Enter Ranges

c© 2009 Andrei Alexandrescu 23 / 52

• To partly avoid these inconveniences, ranges havebeen defined

• A range is a pair of begin/end iterators packed together

• As such, a range has higher-level checkable invariants

• Boost and Adobe libraries defined ranges

Page 36: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 24 / 52

They made an interesting step in a good direction.

Page 37: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 25 / 52

Things must be taken much further.

Page 38: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Look, Ma, no iterators!

c© 2009 Andrei Alexandrescu 26 / 52

• How about defining ranges instead of iterators as theprimitive structure for iteration?

• Ranges should define primitive operations that do notrely on iteration

• There would be no more iterators, only ranges

• What primitives should ranges support?

Remember, begin/end are not an option

If people squirrel away individual iterators, we’reback to square one

Page 39: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Defining Ranges

c© 2009 Andrei Alexandrescu 27 / 52

• All of <algorithm> should be implementable withranges, and other algorithms as well

• Range primitives should be checkable at low cost

• Yet, ranges should not be less efficient than iterators

Page 40: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Input/Forward Ranges

c© 2009 Andrei Alexandrescu 28 / 52

template<class T> struct InputRange {

bool empty() const;

void popFront();

T& front() const;

};

Page 41: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Verifiable?

c© 2009 Andrei Alexandrescu 29 / 52

template<class T> struct ContigRange {

bool empty() const { return b >= e; }

void popFront() {

assert(!empty());

++b;

}

T& front() const {

assert(!empty());

return *b;

}

private:

T *b, *e;

};

Page 42: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Find

c© 2009 Andrei Alexandrescu 30 / 52

// Original version per STL

template<class It, class T>

It find(It b, It e, T value) {

for (; b != e; ++b)

if (value == *b) break;

return b;

}

...

auto i = find(v.begin(), v.end(), value);

if (i != v.end()) ...

Page 43: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Design Question

c© 2009 Andrei Alexandrescu 31 / 52

• What should find with ranges look like?

1. Return a range of one element (if found) or zeroelements (if not)?

2. Return the range before the found element?

3. Return the range after the found element?

Page 44: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Design Question

c© 2009 Andrei Alexandrescu 31 / 52

• What should find with ranges look like?

1. Return a range of one element (if found) or zeroelements (if not)?

2. Return the range before the found element?

3. Return the range after the found element?

• Correct answer: return the range starting with the foundelement (if any), empty if not found

Page 45: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Design Question

c© 2009 Andrei Alexandrescu 31 / 52

• What should find with ranges look like?

1. Return a range of one element (if found) or zeroelements (if not)?

2. Return the range before the found element?

3. Return the range after the found element?

• Correct answer: return the range starting with the foundelement (if any), empty if not found

Why?

Page 46: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Find

c© 2009 Andrei Alexandrescu 32 / 52

// Using ranges

template<class R, class T>

R find(R r, T value) {

for (; !r.empty(); r.popFront())

if (value == r.front()) break;

return r;

}

...

auto r = find(v.all(), value);

if (!r.empty()) ...

Page 47: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Elegant Specification

c© 2009 Andrei Alexandrescu 33 / 52

template<class R, class T>

R find(R r, T value);

“Reduces the range r from left until its front is

equal with value or r is exhausted.”

Page 48: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Bidirectional Ranges

c© 2009 Andrei Alexandrescu 34 / 52

template<class T> struct BidirRange {

bool empty() const;

void popFront();

void popBack();

T& front() const;

T& back() const;

};

Page 49: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Reverse Iteration

c© 2009 Andrei Alexandrescu 35 / 52

template<class R> struct Retro {

bool empty() const { return r.empty(); }

void popFront() { return r.popBack(); }

void popBack() { return r.popFront(); }

E<R>::Type& front() const { return r.back(); }

E<R>::Type& back() const { return r.front(); }

R r;

};

template<class R> Retro<R> retro(R r) {

return Retro<R>(r);

}

template<class R> R retro(Retro<R> r) {

return r.r; // klever

}

Page 50: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

How about find_end?

c© 2009 Andrei Alexandrescu 36 / 52

template<class R, class T>

R find_end(R r, T value) {

return retro(find(retro(r));

}

• No more need for rbegin, rend

• Containers define all which returns a range

• To iterate backwards: retro(cont.all())

Page 51: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

find_end with iterators sucks

c© 2009 Andrei Alexandrescu 37 / 52

// find_end using reverse_iterator

template<class It, class T>

It find_end(It b, It e, T value) {

It r = find(reverse_iterator<It>(e),

reverse_iterator<It>(b), value).base();

return r == b ? e : --r;

}

• Crushing advantage of ranges: much terser code

• Easy composition because only one object needs to becomposed, not two in sync

Page 52: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

More composition opportunities

c© 2009 Andrei Alexandrescu 38 / 52

• Chain: chain several ranges together

Elements are not copied!

Category of range is the weakest of all ranges

• Zip: span several ranges in lockstep

Needs Tuple

• Stride: span a range several steps at once

Iterators can’t implement it!

• Radial: span a range in increasing distance from itsmiddle (or any other point)

Page 53: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

How about three-iterators functions?

c© 2009 Andrei Alexandrescu 39 / 52

template<class It1, It2>

void copy(It1 begin, It1 end, It2 to);

template<class It>

void partial_sort(It begin, It mid, It end);

template<class It>

void rotate(It begin, It mid, It end);

template<class It, class Pr>

It partition(It begin, It end, Pr pred);

template<class It, class Pr>

It inplace_merge(It begin, It mid, It end);

Page 54: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

c© 2009 Andrei Alexandrescu 40 / 52

“Where there’s hardship, there’s opportunity.”

– I. Meade Etop

Page 55: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

3-legged algos ⇒ mixed-range algos

c© 2009 Andrei Alexandrescu 41 / 52

template<class R1, class R2>

R2 copy(R1 r1, R2 r2);

• Spec: Copy r1 to r2, returns untouched portion of r2

vector<float> v;

list<int> s;

deque<double> d;

copy(chain(v, s), d);

Page 56: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

3-legged algos ⇒ mixed-range algos

c© 2009 Andrei Alexandrescu 42 / 52

template<class R1, class R2>

void partial_sort(R1 r1, R2 r2);

• Spec: Partially sort the concatenation of r1 and r2

such that the smallest elements end up in r1

• You can take a vector and a deque and put the smallestelements of both in the array!

vector<double> v;

deque<double> d;

partial_sort(v, d);

Page 57: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

But wait, there’s more

c© 2009 Andrei Alexandrescu 43 / 52

vector<double> v1, v2;

deque<double> d;

partial_sort(v1, chain(v2, d));

sort(chain(v1, v2, d));

• Algorithms can now operate on any mixture of rangesseamlessly without any extra effort

• Try that with iterators!

Page 58: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

But wait, there’s even more

c© 2009 Andrei Alexandrescu 44 / 52

vector<double> vd;

vector<string> vs;

// sort the two in lockstep

sort(zip(vs, vd));

• Range combinators allow myriads of new uses

• Possible in theory with iterators, but the syntax wouldexplode (again)

Page 59: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Output ranges

c© 2009 Andrei Alexandrescu 45 / 52

• Freedom from pointer syntax allows supporting differenttypes

struct OutRange {

typedef Typelist<int, double, string> Types;

void put(int);

void put(double);

void put(string);

}

Page 60: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Back to copying stdin to stdout

c© 2009 Andrei Alexandrescu 46 / 52

#include <...>

int main() {

copy(istream_range<string>(cin),

ostream_range(cout, "\n"));

}

• Finally, a step forward: a one-liner that fits on one line1

• ostream_range does not need to specify string

1slide limitations notwithstanding

Page 61: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Infinite ranges

c© 2009 Andrei Alexandrescu 47 / 52

• Notion of infinity becomes interesting with ranges

• Generators, random numbers, series, . . . are infiniteranges

• Infinity is a trait distinct from the five classic categories;any kind of range may be infinite

• Even a random-access range may be infinite!

• Statically knowing about infinity helps algorithms

Page 62: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

has_size

c© 2009 Andrei Alexandrescu 48 / 52

• Whether a range has an efficiently computed size isanother independent trait

• (Index entry: list.size, endless debate on)

• Even an input range can have a known size, e.g.take(100, rndgen) which takes 100 randomnumbers

◦ take(100, r) has length 100 if r is infinite◦ length min(100, r.size()) if r has known

length◦ unknown length if r is finite with unknown length

Page 63: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

A Twist

c© 2009 Andrei Alexandrescu 49 / 52

• Can <algorithm> be redone with ranges?

• D’s stdlib offers a superset of <algorithm> in modulesstd.algorithm and std.range (google for them)

• Ranges pervade D: algorithms, lazy evaluation, randomnumbers, higher-order functions, foreachstatement. . .

• Some opportunities not yet tapped—e.g. filters(input/output ranges)

• Check “The Case for D” in Doctor Dobb’s Journal,coming soon

Page 64: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Conclusion

c© 2009 Andrei Alexandrescu 50 / 52

• Ranges are a superior abstraction

• Better checking abilities (not perfect still)

• Easy composition

• Range-based design offers much more than a port ofiterator-based functions to ranges

• Exciting development taking STL one step further

Page 65: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Announcement

c© 2009 Andrei Alexandrescu 51 / 52

Please note: “The D ProgrammingLanguage” soon to appear on Safari’s

Rough Cuts.

Page 66: Iterators Must Go - ACCU...Warning Sign #4 c 2009 Andrei Alexandrescu 20 / 52 • Iterators use pointer syntax & semantics • Integration with pointers for the win/loss • However,

Andrei Alexandrescu, Ph %@! D

c© 2009 Andrei Alexandrescu 52 / 52

Please note: Andrei will soon be offeringtraining and consulting services. Contact

him for details.