cnt_votes(vector<unsigned> votes) vector<unsigned> candidates(n) 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(unsigned vote) candidates[vote]++
candidates
come?
candidates
must be left as a global.
static vector<unsigned> candidates(n) static void count_vote(int vote) candidates[vote]++ cnt_votes(vector<unsigned> & votes) candidates = vector<unsigned>(n) std::for_each( votes.begin(), votes.end(), count_vote)
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 operator () ( argument-list ) }
struct count { void operator () (int i); }
callable c; int i = c(1);
callable c = callable() // instance creation int i = c() // instance calling
callable
is a functor name.
c
is a function-object name.
struct vote_count { std::vector<unsigned> & candidates; vote_count(std::vector<unsigned> & c) : candidates(c) { } void operator () (unsigned v) { candidates[v]++ } }; cnt_votes(vector<unsigned> & votes) std::vector<unsigned> candidates vote_count vc(candidates); for_each(votes.begin(), votes.end(), vc); cout << "Candidate 0 got " << 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
.
bool is_a_vote(unsigned v) { return a == v } bool is_b_vote(unsigned v) { return b == v } acount = count_if(h.begin(), h.end(), is_a_vote) bcount = count_if(h.begin(), h.end(), is_b_vote) ccount = count_if(h.begin(), h.end(), is_c_vote)
bool is_vote(unsigned c, unsigned v) return c == v
std::count_if()
requires a unary predicate, not a binary (two
argument) one.
count_if(h.begin(), h.end(), is_vote)
c
get a value?
struct is_vote { const unsigned candidate is_vote(unsigned c) : candidate(c) { } bool operator () (unsigned vote) const { return candidate == vote; } };
acount = count_if(h.begin(), h.end(), is_vote(a)) bcount = count_if(h.begin(), h.end(), is_vote(b)) ccount = count_if(h.begin(), h.end(), is_vote(c))
<functional>
.
std::bind2nd()
and std::bind1st()
function adaptors.
std::bind1st(fo, val)
accepts the function object
struct fo { operator () (x, y) { ... } }
and argument value val
and returns the function object
struct fo' { operator () (y) { fo(val, y) } }
sd::bind2nd(fo, val)
accepts the function object
struct fo { operator () (x, y) { ... } }
and argument value val
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_vote()
doesn't work with std::count_if()
.
is_vote(unsigned c, unsigned v)
has two arguments; can't
set c
.
std::bind1st()
can solve these problems.
is_vote()
from a function to a function object with
std::ptr_fun()
.
std::ptr_fun(is_vote)
s
for is_vote()
with std::bind1st()
.
std::bind1st(std::ptr_fun(is_vote), a)
unsigned count_votes(vector<unsigned> votes, int c) return count_if( votes.begin(), votes.end(), std::bind1st(std::fun_ptr(is_vote), c)) vector<unsigned> s_counts(4) for unsigned i = 0; i < 4; i++ s_counts[i] = count_vote(votes, 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
std::find_if()
is looking for the wrong thing.
std::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()
.
std::not1()
and std::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";
std::map< typename Key, typename Value, class C = std::less<Key> class Allocator = . . . >;
static bool pt_greater( const point & p1, const point & p2) return . . . int main() map<point, string,pt_greater> pt_map;
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 24 March 2004.