cnt_votes(vector<int> votes) vector<unsigned> candidates(votes.size()) for unsigned i = 0; i < votes.size(); i++ candidates[votes[i]]++
std::for_each(b, e, f)
is a good candidate.
f()
for each value in the range (b, e)
.
std::for_each()
with the function
void count_vote(int vote) candidates[vote]++
candidates
come?
candidates
must be left as a global.
vector<unsigned> candidates(n) cnt_votes(vector<int> & votes) for (unsigned i = 0; i < votes.size(); i++) candidates[votes[i]]++
candidates
.
()
can be defined in classes and structs.
operator ()
allows class instances to be called as if
they were functions.
struct callable { char operator () (int i, string s) { ... } }; callable c; char ch = c(1, "hello");
operator
()
member functions.
callable
is a functor.
c
is a function object; that is, an object that responds as if
it were a function.
struct name { return-type-spec operator () ( argument-list-decls ) }
struct count { void operator () (int i); }
callable c; int i = c(1);
callable c = callable() // instance creation int i = c() // instance calling
struct vote_count { vector<unsigned> candidates; vote_count(unsigned n) : candidates(n) { } void operator () (unsigned v) { candidates[v]++ } }; cnt_votes(vector<unsigned> & votes) vote_count vc(n); for_each(votes.begin(), votes.end(), vc); cout << "Candidate 0 got " << vc.candidates[0] << " votes";
c.operator()(1, "hello")
works via member function access.
isdigit.operator()('c')
fails because isdigit()
isn't a class.
template < typename testT > bool is_str_type(string str, testT test) for unsigned i = 0; i < str.size(); i++ if !test(str[i]) return false return true
test
.
unsigned count = 0 for unsigned i = 0; i < votes.size(); i++ if votes[i] == c count++
count()
and count_if()
.
count(b, e, c)
returns the number of votes for the candidate
c
.
count_if(b, e, p)
returns the number of elements satisfying
p()
.
p()
is a unary (one-argument) predicate (boolean
returning function).
bool is_c_vote(unsigned v) return c == v
as the predicate for count_if()
?
count = count_if(votes.begin(), votes.end(), is_c_vote)
bool is_cj_vote(unsigned v) { return cj == v } bool is_ck_vote(unsigned v) { return ck == v } cicount = count_if(h.begin(), h.end(), is_ci_vote) cjcount = count_if(h.begin(), h.end(), is_cj_vote) ckcount = count_if(h.begin(), h.end(), is_ck_vote)
bool is_vote(unsigned c, unsigned v) return c == v
count_if()
requires a unary predicate, not a binary (two
argument) one.
count_if(h.begin(), h.end(), is_vote)
c
get a value?
<functional>
.
bind2nd()
and bind1st()
function adaptors.
bind1st(fo, val)
accepts the function object
struct fo { operator () (x, y) { ... } }
and returns the function object
struct fo' { operator () (y) { fo(val, y) } }
bind2nd(fo, val)
accepts the function object
struct fo { operator () (x, y) { ... } }
and returns the function object
struct fo' { operator () (x) { fo(x, val) } }
bind
adapters work on function objects, not functions.
std::ptr_fun()
converts a function to a function
object.
void zero(void) { ... } void one(int i) { ... } void two(int i, string j) { ... } void three(int i, int j, int k) { ... }std::ptr_fun(zero)std::ptr_fun(one) std::ptr_fun(two)std::ptr_fun(three)
std::ptr_fun()
can be a pain.
is_cj_vote()
doesn't work with std::count_if()
.
is_cj_vote(unsigned c, unsigned v)
has two arguments; can't
set c
.
bind1st()
can solve these problems.
is_vote()
from a function to a function object with
std::ptr_fun()
.
std::ptr_fun(is_cj_vote)
s
for is_vote()
with std::bind1st()
.
std::bind1st(std::ptr_fun(is_vote), cj)
unsigned count_votes(vector<unsigned> votes, int c) return count_if(votes.begin(), votes.end(), bind1st(fun_ptr(is_vote), c)) vector<unsigned> s_counts(4) for unsigned i = 0; i < 4; i++ s_counts[i] = count_vote(votes, i)
unsigned count_vote(vector<unsigned> votes, int c) return std::count_if(votes.begin(), votes.end(),is_vote<c>);
c
in is_vote<c>
is not known at compile time.
template < unsigned c > unsigned count_vote(std::vector<unsigned> votes) return std::count_if(votes.begin(), votes.end(), is_vote<c>);
isstrtype
Revisitedisstrtype()
? It applied <cctype>
predicates to
strings.
bool isstrtype(string s, bool (* ctp)(char)) for (unisgned i = 0; i < s.size(); i++) if (!ctp(s[i])) return false return true
std::find_if()
?
bool isstrtype(string s, bool (* ctp)(char)) string::iterator e = s.end() returnfind_if(s.begin(), e, ctp)== e
find_if()
is looking for the wrong thing.
find_if()
looks for characters of the type (digit, for
example) and skips characters not of the type.
isstrtype()
looks for characters not of the type (digit, for
example) and skips characters of the type.
ctp()
is the wrong predicate; it should be not_ctp()
.
not1()
and not2
function adaptors.
not1(fo)
accepts the function object
struct fo { bool operator () (x) { ... } }
and returns the function object
struct fo' { bool operator () (x) { return !fo(x) } }
not2(fo)
accepts the function object
struct fo { bool operator () (x, y) { ... } }
and returns the function object
struct fo' { bool operator () (x, y) { return !fo(x, y) } }
isstrtype()
and Function Adaptersstd::not1()
solve this problem?
find_if(s.begin(), s.end(), not1(ctp))
not1()
works on function objects, not functions.
fun_ptr()
to convert a function to a function object.
bool isstrtype(string s, bool (* ctp)(char)) return find_if(s.begin(), s.end(), not1(ptr_fun(ctp))) while getline(std::cin, str) if isstrtype(str, isspace) continue if !isstrtype(str, isdigit) std::cerr << "Number expected.\n";
less
.
class pt_less { bool operator () (point a, point b) { return a < b; } }; map<point, unsigned, pt_less> points;
write instead
map<point, unsigned, less<point> > points;
plus
, minus
, multiplies
, ...
equal_to
, less_equal
, ...
logical_not
, logical_or
, ...
operator ()
member functions.
This page last modified on 17 November 2003.