c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore

6. Indirect Functoids

Table of Contents

6.1. Subtype-polymorphism
6.2. Relation to boost::function

Indirect functoids are "function variables" which can be dynamically bound to any function with the right monomorphic type signature. Recall the example from Section 4:

   fun2<int,int,int> f = plus;  
   f(3,2);          // yields 5
   f = minus;
   f(3,2);          // yields 1
Here f is an indirect functoid, which can be bound to different functions (plus and minus, in the example) during its lifetime. Indirect functoids are declared as instances of the funN classes, where N is the arity of the function and the N+1 template arguments name the argument types and the return type.

Indirect functoids are necessarily monomorphic. This restriction is rooted in the implementation: indirect functoids are implemented using dynamic dispatch (virtual function call), and in C++, a virtual method cannot also be a member template. When an indirect functoid is initialized or assigned the value of a polymorphic direct functoid, the appropriate monomorphic function is selected. For example:

   std::string foo="foo", bar="bar";
   fun2<std::string,std::string,bool> sl = less;
   sl(foo,bar);    // yields false
   fun2<int,int,bool> il = less;
   il(2,3);        // yields true
Here we use the FC++ polymorphic functoid less (which has the general signature (T,T)->bool) to initialize two different indirect functoids. Each indirect functoid selects the appropriate monomorphic instantiation of the polymorphic functoid it is initialized with.

6.1. Subtype-polymorphism

Indirect functoids exhibit subtype-polymorphism (the dynamic polymorphism OO programmers are familiar with). This works in the expected way; indirect functoids are contravariant in their argument types and covariant in their return types. An example makes this clear: suppose there are two inheritance hierachies, one where dog is derived from animal and another where car is derived from vehicle. Then we can say

   fun1<dog*,vehicle*> f = ...; 
   fun1<animal*,car*> g = f;    // ok
   f = g;                       // illegal (type error)
f is effectively a subtype of g; wherever g is used, f can be supplied as a legal implementation, but not the other way around.

6.2. Relation to boost::function

Indirect functoids in FC++ are similar to boost::function objects. There are a few notable differences. First, indirect functoids must always be initialized with a function value (there is no default constructor or the equivalent of a "null" function). Second, indirect functoids have all the FC++ full functoids features (like built-in currying and infix syntax, described in the next section), whereas boost::function objects do not. On the other hand, indirect functoids always pass parameters by const&, whereas boost::function objects can have parameters passed by plain reference, allowing for mutation of arguments to the function object.

Last revised: October 03, 2003 at 23:27:22 GMTCopyright © 2000-2003 Brian McNamara and Yannis Smaragdakis