cnt_suits(vectorhand) unsigned suits[] = { 0, 0, 0, 0 }; for (unsigned i = 0; i < hand.size(); i++) suits[hand[i].suit]++
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_suit(const card & c) assert(is_suit(c.suit)) suits[c.suit]++
suits
come?
suits
must be left as a global.
unsigned suits[] = { 0, 0, 0, 0 } cnt_suits(vector& hand) for (unsigned i = 0; i < hand.size(); i++) suits[hand[i].suit]++
suits
.
()
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 suit_count { unsigned suits[] = { 0, 0, 0, 0 } void operator () (card c) { assert(is_suit(c.suit); suits[c.suit]++ } }; cnt_suits(vector& hand) suit_count sc; for_each(hand.begin(), hand.end(), sc); cout << "There were " << sc.suits[0] << " clubs";
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 < hand.size(); i++ if hand[i].suit == heart count++
count()
and count_if()
.
count(b, e, c)
returns the number of elements equal to the
single card 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_heart_card(card c) return c.suit == heart
as the predicate for count_if()
?
count = count_if(hand.begin(), hand.end(), is_heart_card)
bool is_spade_card(card c) { return c.suit == spade } bool is_club_card(card c) { return c.suit == club } hcount = count_if(h.begin(), h.end(), is_heart_card) ccount = count_if(h.begin(), h.end(), is_club_card) scount = count_if(h.begin(), h.end(), is_spade_card)
bool is_suit(card c, int suit) return c.suit == suit
count_if()
requires a unary predicate, not a binary (two
argument) one.
count_if(h.begin(), h.end(), is_suit)
suit
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_heart_suit()
doesn't work with std::count_if()
.
is_suit(card c, int s)
has two arguments; can't set s
.
bind2nd()
can solve these problems.
is_suit()
from a function to a function object with
std::ptr_fun()
.
std::ptr_fun(is_suit)
s
for is_suit()
with std::bind2nd()
.
std::bind2nd(std::ptr_fun(is_suit), s)
unsigned count_suit(vectorhand, int s) return count(hand.begin(), hand.end(), bind2nd(fun_ptr(is_suit), s)) vector<unsigned> s_counts(4) for unsigned i = 0; i < 4; i++ s_counts[i] = count_suit(hand, i)
bool is_club(card c) return c.suit == club bool is_diamond(card c) return c.suit == diamond bool is_heart(card c) return c.suit == heart bool is_spade(card c) return c.suit == spade
is duplicate code, differing only in the suit.
template <card::suit s> bool is_suit(card c) return c.suit == s
unsigned hearts = std::count_if(hand.begin(), hand.end(), is_suit<card::heart>);
unsigned count_suit(vector<card> hand, card::suit s) return std::count_if(hand.begin(), hand.end(),is_suit<s>);
s
in is_suit<s>
is not known at compile time.
template < card::suit s > unsigned count_suit(std::vector<card> hand) return std::count_if(hand.begin(), hand.end(), is_suit<s>);
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
, ...
operator ()
member functions.
This page last modified on 27 March 2003.