cnt_wds(istream & is) map<string, unsigned> wd_cnt while is >> str wc_cnt[str]++
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_wd(string wd) wd_cnt[wd]++
wd_cnt
come?
wd_cnt
must be left as a global.
map<string, unsigned> wd_cnt cnt_wds(istream & is) for_each(istream_iterator<string>(is), istream_iterator<string>(), count_wd)
wd_cnt
.
()
can be defined within 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);
*
needed.
callable c;int i = (* c)(1);
callable c = callable() // instance creation int i = c() // instance calling
struct word_count { map<string, unsigned> wdcnt; void operator () (string wd) { wdcnt[wd]++ } }; cnt_wds(istream & is) word_count wc; for_each(istream_iterator<string>(is), istream_iterator<string>(), wc) cout << wc.wdcnt.size() << "words read.\n"
&c
is not a function pointer; it's a pointer to callable class
value.
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
.
int
s in a vector are congruent to 0 mod 3?
unsigned count = 0 for unsigned i = 0; i < iv.size(); i++ if iv[i] % 3 == 0 count++
count()
and count_if()
.
count(b, e, 0)
returns the number of zero elements.
count_if(b, e, p)
returns the number of elements satisfying
p()
.
p()
is a unary (one-argument) predicate (boolean
returning function).
bool zm3(int i) return (i % 3) == 0
as the predicate for find_if()
?
count = count_if(iv.begin(), iv.end(), zm3)
bool om3(int i) { return (i % 3) == 1 } bool tm3(int i) { return (i % 3) == 2 } count0 = count_if(iv.begin(), iv.end(), zm3) count1 = count_if(iv.begin(), iv.end(), om3) count2 = count_if(iv.begin(), iv.end(), tm3)
bool cm3(int i, int r) return (i % 3) == r
find_if()
requires a unary predicate, not a binary (two
argument) one.
count_if(iv.begin(), iv.end(), cm3)
r
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.
cm3()
doesn't work with std::find_if()
.
cm3(int i, int r)
has two arguments; can't set r
.
bind2nd()
can solve these problems.
cm3()
from a function to a function object with
std::ptr_fun()
.
std::ptr_fun(cm3)
r
for cm3
with std::bind2nd()
.
std::bind2nd(std::ptr_fun(cm3), r)
unsigned count_residues(ivec iv, int r) return find_if(iv.begin(), iv.end(), bind2nd(fun_ptr(cm3), r)) const unsigned modulus = 3 vector<unsigned> r_counts(modulus) for unsigned i = 0; i < modulus; i++ r_counts[i] = count_residues(iv, i)
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_cpt()
.
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))
ctp()
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
, ...
cm3()
Revisitedcm3(int i, int r)
didn't work with count_if()
.
r
.
bind2nd()
works with cm3()
, but is there another way?
bool zm3(int i) { return (i % 3) == 0 } bool om3(int i) { return (i % 3) == 1 } bool tm3(int i) { return (i % 3) == 2 }
template < int res > bool cm3(int i) { return (i % 3) == res; }
c0 = count_if(iv.begin(), iv.end(), cm3<0>) c1 = count_if(iv.begin(), iv.end(), cm3<1>) c2 = count_if(iv.begin(), iv.end(), cm3<2>)
operator ()
member functions.
This page last modified on 8 November 2002.