Attached is a sample code that implements the three approaches that Lars has 
been playing with.

        std::string const search_name = "william";

        FooVec::const_iterator const begin = foovec.begin();
        FooVec::const_iterator const end = foovec.end();

        FooVec::const_iterator const it = std::find_if(begin, end,
#if CASE == 1
                             SameNames(search_name));
#elif CASE == 2
                             boost::bind(std::equal_to<std::string>(),
                                         boost::bind(&Foo::name, _1),
                                         search_name));
#elif CASE == 3
                             bind(&Foo::name, _1) == search_name);
#endif

Compile, eg:
$ g++ -DCASE=1 -Iboost/boost-1.30.2 -O2 -o trial trial.C
$ CASE=3;
$ g++ -DCASE=$CASE -Iboost/boost-1.30.2 -O2 -S -o trial_case$CASE.s trial.C

I have little idea how to make sense of the assembler code but, at least for 
gcc 3.3, it appears that the named functor approach produces the 
smallest-sized executable.

$ size trial_case?
   text    data     bss     dec     hex filename
   7850     816       8    8674    21e2 trial_case1
   9510     840      16   10366    287e trial_case2
   9530     872       8   10410    28aa trial_case3

Regards,
Angus


#include <iostream>
#include <string>
#include <vector>

#if !defined(CASE) || (CASE != 1 && CASE != 2 && CASE != 3)
#error Please compile -DCASE=[123]
#endif

#if CASE == 2
#include <boost/bind.hpp>
using namespace boost;
#endif

#if CASE == 3
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
using namespace boost::lambda;
#endif


class Foo {
	std::string name_;
public:
	Foo(std::string const & name) : name_(name) {}
	std::string const & name() const { return name_; }
};


char const * const names[] = {
	"alfred", "ben", "chris", "david", "edgar", "fred", "graham",
	"henry", "ian", "james", "kenneth", "laurie", "mark", "nigel",
	"oprah", "peter", "quentin", "rashid", "stewart", "thomas",
	"uriah", "veronique", "william", "xang", "yashin", "zebedee"
};

std::size_t const names_size = sizeof(names) / sizeof(names[0]);


#if CASE == 1
struct SameNames {
	SameNames(std::string const & name) : name_(name) {}
	bool operator()(Foo const & foo) const
		{ return name_ == foo.name(); }
private:
	std::string name_;
};
#endif


int main()
{
	typedef std::vector<Foo> FooVec;
	FooVec const foovec(names, names + names_size);

	std::string const search_name = "william";

	FooVec::const_iterator const begin = foovec.begin();
	FooVec::const_iterator const end = foovec.end();

#if CASE == 1
	FooVec::const_iterator const it =
		std::find_if(begin, end, SameNames(search_name));
#elif CASE == 2
	FooVec::const_iterator const it =
		std::find_if(begin, end,
			     boost::bind(std::equal_to<std::string>(),
					 boost::bind(&Foo::name, _1),
					 search_name));
#elif CASE == 3
	FooVec::const_iterator const it =
		std::find_if(begin, end,
			     bind(&Foo::name, _1) == search_name);
#endif

	if (it == end)
		std::cout << "Name '" << search_name << "' not found"
			  << std::endl;
	else
		std::cout << "Name '" << search_name <<  "' found at pos "
			  << std::distance(begin, it)
			  << std::endl;

	return 0;
}

Reply via email to