More C++ Idioms/Object Generator
Object Generator
edit
Intent
editTo simplify creation of objects without explicitly specifying their types. (This is not the factory method pattern)
Also Known As
editMotivation
editIn C++ template programming, types of objects can get really large and incomprehensible even in small programs. For example, the following type (Wrapper) is a standard unary function object that wraps the member function read_line in class File.
struct File
{
int read_line (std::string);
};
typedef std::mem_fun1_t<int, File, std::string> Wrapper;
Reading a collection of files using the for_each STL algorithm, without object generators, looks like the following:
void read_lines(std::vector<File *> files)
{
typedef std::mem_fun1_t<int, File, std::string> Wrapper;
std::string arg;
for_each(files.begin(), files.end(),
std::binder2nd<Wrapper>(Wrapper(&File::read_line), arg));
}
The above code is pretty much unreadable and more bloated than necessary. Even typedefs don't improve readability as placeholder typedefs like Wrapper are distracting. The object generator idiom alleviates the situation.
Solution and Sample Code
editIn the object generator idiom, a template function is created whose only job is to construct a new object from its parameters. It is based on a useful property of function templates which class templates don't have: The type parameters of a function template are deduced automatically from its actual parameters. For example, consider a simple object generator defined in STL: make_pair.
template <class T, class U>
std::pair <T, U>
make_pair(T t, U u)
{
return std::pair <T, U> (t,u);
}
make_pair returns an instance of the pair template depending on the actual parameters of the make_pair function. For example, make_pair(1,1.0) creates an object of type: std::pair<int, double> by automatically deducing the types of the objects being passed to the object generator function. make_pair is particularly handy in the case where a generated pair object does not need to be stored in a local variable.
map <int, double> m;
m.insert (make_pair(1,1.0)); // No need to know how pair template is instantiated.
The C++ standard library defines several object generators to avoid code bloat. std::bind2nd and std::mem_fun are two such standard object generators that can be used to avoid code bloat in the example shown in the motivation section above.
void read_lines(std::vector<File *> files)
{
std::string arg;
for_each(files.begin(), files.end(), bind2nd(mem_fun(&File::read_line), arg));
}
Known Uses
editC++ standard library (mem_fun, make_pair, bind1st, bind2nd etc.)