Alright this is about
choosing abstractions,
so we got a really simple problem here.
You got a string like this,
you wanna snip the beginning
you wanna snip the end,
you wanna take the little,
the spaces in between, compress
them into a single space
something like this right?
The way you solve this
is with a state machine.
You guys all know this right.
This is just a find state
automaton, if you're in
state one and you get a
space, stay into state one.
If you go to state one,
state two you've taken
that character that isn't
a space and you've put it
out to the output and so on and so forth.
State two, state three.
Anyway, this works and
we don't really care.
This is what the code looks
like, it's very basic.
You have an enum that
you define and you have
the state transitions
within this list statement.
(audience laughs)
What's so funny about this?
This is not funny.
(audience laughs)
Alright.
(audience laughs)
tell me later, alright
what I really care about is
how do we, what do we
want our interface to be.
In C++ 98 style you'd
take in a string reference
and you know how you use this thing right.
If you have a string
that you want to modify
you call it clean_whitespace
on your string and then
it goes ahead and modifies the reference
that you passed as your argument. Fine.
If you want to take a second
string that's equivalent to
the first, but this clean_whitespace
thing is applied to it.
You make a copy of the original
string and then you call
clean_whitespace on that.
That's not really nice but it works.
You can do C++ 11 style,
you can take in the string
by value, I'm not gonna show
you how to do this right.
You basically take that in
by value, you move the result
onto the string so this
modifies the string in place
and whatever returns the result.
So if you want to modify a
string in place, you call
stood move on your argument and then set
the result equal to s and
then it doesn't do any
extra memory allocations, right.
It's kinda weird though,
you're putting in this strange
stood move thing and I
guess you're sprinkling
performance annotations, I don't know.
But if you do wanna take a s2
and make it equivalent to s1
that has the clean_whitespace
applied to it you can do that.
So yeah, that works, that looks nice.
Or you can be STL style.
(audience groans)
I hear groans, like this is
(audience laughs)
this is cool, wait to you get to where
I tell ya what the best thing is.
Alright, so here you take an InputIterator
and you return an
OutputIterator and you also get
an OutputIterator as an
argument, basically the idea is
it sets the output to the results
and returns one past
the last OutputIterator.
So if you have a string, and
you wanna take a second string
and apply this operation to
the first string to result
in the second string, you do this.
Call s.begin, s.end as
your first two arguments
and you send in a back_inserter(s2).
It's not, that bad well
compared to the other ones
it's really bad but it does the thing.
So if you have a single
string and you wanna apply it
this operation in place,
you can do that too.
With the STL style you
pass s.begin as your result
as well as your argument to the thing.
Of course though this does it in place
and there's a little
bit left over in the end
of the string so you gotta
do that s.erase to it.
You can do that, it's really cool.
You can also take your
instream, your standard input,
convert these into istream_iterators
and use an ostream_iterator
with std to cout
and you can basically design a function,
or design a program which takes the input
and applies this operation to the output.
With just one thing, so
it's extremely flexible.
But this code's insane
(audience laughs)
but it is really flexible.
So there's also, you
could have native style.
Because as we saw in the
find state automaton,
where you take in, where it just
basically has a get and a put.
You can define your function
in terms of abstract types
that just have, act like
function calls with get and put.
And the question is, which
is the right interface?
So, they all have benefits and drawbacks
what do you think?
- [Audience] All of them.
All of them, like seriously
you're gonna write
this function and provide
four interfaces to it?
(audience laughs)
- [Audience] Benchmark it.
Benchmark it, these are all
gonna be about the same.
- [Audience] The last one.
- [Audience] Ranges v3.
The last one? Ranges v3? What?
(audience laughs)
I'm not gonna use ranges
v3, then we're pulling
a whole new crazy dependency.
- [Audience] Vector of string views.
Vector of String Views.
(audience laughs)
We have a funny crowd, do we
really not know the answer
to this question, which one's superior?
I mean if you do the STL
style you can implement
the other ones on top of it.
Actually if you want to
implement that last one
on top of the STL style think about
how nasty that would be, right?
You'd have to make iterators
out of put and get, thanks.
Oh, alright, well
(beeping sound)
I'm gonna give you the answer
but I'm out of time so--
(audience laughing and applause)
