/*
 * $Id$
 *
 * Created: 2.2.2007
 * Author: jedi
 *
 * Generalized functors provide statically type checked way of
 * defining functors with variable number of parameters (via typelists).
 * Generalized functors also handle implicit type conversions, pointers
 * to regular functions and member functions (instead of
 * SomeClass::operator()) and parameter binding to a constant value.
 */


#include <iostream>
#include <loki/TypelistMacros.h>
#include <loki/Functor.h>


using namespace std;
using namespace Loki;


/// free function that performs arithmetic division
double divide(double dividend, double divisor)
{
   return dividend / divisor;
}

/// command class that provides two commands
struct inverter
{
      /// "normal" way of defining a command function
      int operator()(int i) {return (-1 * i);}

      /// use member function instead of operator(),
      /// also the parameter is passed by reference
      void invert(string& sz) {reverse(sz.begin(), sz.end());}
};

// *** program output:
//
// 3 inverts to -3
// jedi inverts to idej
// 0.75
// 0.5
//
int main()
{
   // instance of the command class
   inverter c;

   // 1: create and invoke the inverter::operator() functor
   Functor<int, LOKI_TYPELIST_1(int)> inverter_i(c);
   cout << "3 inverts to " << inverter_i(3) << endl;

   // 2: create and invoke the inverter::invert() functor
   Functor<void, LOKI_TYPELIST_1(string&)> inverter_sz(&c, &inverter::invert);
   string jedi = "jedi";
   inverter_sz(jedi);
   cout << "jedi inverts to " << jedi << endl;

   // 3 & 4: two divider fuctors. the second one only needs one parameter
   // as the first parameter is bound to a constant value
   Functor<double, LOKI_TYPELIST_2(double, double)> divider(divide);
   Functor<double, LOKI_TYPELIST_1(double)> bound_divider(
      BindFirst(divider, 2.0));  // bind the dividend to 2
   int dividend = 3;
   int divisor = 4;
   cout << divider(dividend, divisor) << endl; // implicit type conversion
   cout << bound_divider(divisor) << endl;

   return 0;
}