// Invocation of pointers which supply the parameter type. Full invocation
// with paramters is posesible in this fashion with out knowing the class
// that the functor refers to.
void testGlobalReturnParams()
{
  ArGlobalRetFunctor<bool> functor(retFunction);
  ArGlobalRetFunctor1<char*, int> functor1(retFunction, 1);
  ArGlobalRetFunctor2<double, bool, std::string>
    functor2(retFunction, false, "default arg");
  ArRetFunctor<bool> *fBoolPtr;
  ArRetFunctor1<char*, int> *fCharPtr;
  ArRetFunctor2<double, bool, std::string> *fDoublePtr;
  bool bret;
  char *cret;
  double dret;

  printf("\n****** Testing global pointer invocation with return\n");
  fBoolPtr=&functor;
  puts("> bool retFunction() should return true...");
  bret=fBoolPtr->invokeR();
  printf("Returned: %d\n", bret);
  fCharPtr=&functor1;
  puts("> char* retFunction(7) should return \"Hello\"...");
  cret=fCharPtr->invokeR(7);
  printf("Returned: %s\n", cret);
  fDoublePtr=&functor2;
  puts("> double retFunction(false, \"argument 3\") should return 4.62...");
  dret=fDoublePtr->invokeR(false, "argument 3");
  printf("Returned: %e\n", dret);
}
void testReturnParams()
{
  TestClass test;
  ArRetFunctorC<bool, TestClass> functor(test, &TestClass::retFunction);
  ArRetFunctor1C<char*, TestClass, int>
    functor1(test, &TestClass::retFunction, 1);
  ArRetFunctor2C<double, TestClass, bool, std::string>
    functor2(test, &TestClass::retFunction, false, "default arg");
  ArRetFunctor<bool> *fBoolPtr;
  ArRetFunctor1<char*, int> *fCharPtr;
  ArRetFunctor2<double, bool, std::string> *fDoublePtr;
  bool bret;
  char *cret;
  double dret;

  printf("\n****** Testing pointer invocation with return\n");
  fBoolPtr=&functor;
  puts("> TestClass::retFunction() should return true");
  bret=fBoolPtr->invokeR();
  printf("Returned: %d\n", bret);
  fCharPtr=&functor1;
  puts("> TestClass::retFunction(7) should return \"Hello\"");
  cret=fCharPtr->invokeR(7);
  printf("Returned: %s\n", cret);
  fDoublePtr=&functor2;
  puts("> TestClass::retFunction(false, \"argument 3\") should return 4.62...");
  dret=fDoublePtr->invokeR(false, "argument 3");
  printf("Returned: %e\n", dret);
}
// Direct invocation of the functors with return values and supplying
// parameters. It is not posesible to have the operator() for functors with
// return values. This is due to limitations of C++ and different C++
// compilers where you can not overload return values in all cases.
void testReturnDirect()
{
  TestClass test;
  ArRetFunctorC<bool, TestClass> functor(test, &TestClass::retFunction);
  ArRetFunctor1C<char*, TestClass, int>
    functor1(test, &TestClass::retFunction, 1);
  ArRetFunctor2C<double, TestClass, bool, std::string>
    functor2(test, &TestClass::retFunction, false, "default arg");
  bool bret;
  char *cret;
  double dret;

  //bret=test.retFunction();
  //cret=test.retFunction(4);
  //dret=test.retFunction(true, "foof");

  printf("\n****** Testing direct invocation with return\n");
  puts("> TestClass::retFunction() should return true...");
  bret=functor.invokeR();
  printf("Returned: %d\n", bret);
  puts("> TestClass::retFunction(5) should return \"Hello\"...");
  cret=functor1.invokeR(5);
  printf("Returned: %s\n", cret);
  puts("> TestClass::retFunction(true, \"argument 1\") should return 4.62...");
  dret=functor2.invokeR(true, "argument 1");
  printf("Returned: %e\n", dret);
}
// Direct invocation of the global functors with supplying parameters.
void testGlobalDirect()
{
  ArGlobalFunctor functor(&function);
  ArGlobalFunctor1<int> functor1(&function, 1);
  ArGlobalFunctor2<bool, std::string> functor2(&function,
					       false, "default arg");

  printf("\n****** Testing global direct invocation\n");
  puts("> Should see function()...");
  functor.invoke();
  puts("> Should see function(5)...");
  functor1.invoke(5);
  puts("> Should see function(true, \"argument 1\")...");
  functor2.invoke(true, "argument 1");
}
// Invocation of a base ArFunctor pointer to a global functor. Because the
// pointer is of type ArFunctor, the parameters can not be supplied. The
// default parameters, which are supplied when the functor is constructed,
// are used.
void testGlobalBase()
{
  ArFunctor *fptr;
  ArGlobalFunctor functor(function);
  ArGlobalFunctor1<int> functor1(function, 1);
  ArGlobalFunctor2<bool, std::string> functor2(function, false,
						"default arg");

  printf("\n****** Testing global base invocation\n");
  fptr=&functor;
  puts("> Should see function()...");
  fptr->invoke();
  fptr=&functor1;
  puts("> Should see function(1)...");
  fptr->invoke();
  fptr=&functor2;
  puts("> Should see function(false, \"default arg\")...");
  fptr->invoke();
}
// Direct invocation of the functors with supplying parameters.
void testDirect()
{
  TestClass test;
  ArFunctorC<TestClass> functor(test, &TestClass::function);
  ArFunctor1C<TestClass, int> functor1(test, &TestClass::function, 1);
  ArFunctor2C<TestClass, bool, std::string> functor2(test,
						     &TestClass::function,
						     false, "default arg");

  printf("\n****** Testing direct invocation using ArFunctor::invoke(...)\n");
  puts("> Should see TestClass::function()...");
  functor.invoke();
  puts("> Should see TestClass::function(1)...");
  functor1.invoke();
  puts("> Should see TestClass::function(5)...");
  functor1.invoke(5);
  puts("> Should see TestClass::function(true, \"argument 1\")...");
  functor2.invoke(true, "argument 1");
}
// Direct invocation of the global functors with supplying parameters.
void testGlobalReturnDirect()
{
  ArGlobalRetFunctor<bool> functor(&retFunction);
  ArGlobalRetFunctor1<char*, int> functor1(&retFunction, 1);
  ArGlobalRetFunctor2<double, bool, std::string>
    functor2(&retFunction, false, "default arg");
  bool bret;
  char *cret;
  double dret;

  printf("\n****** Testing global direct invocation with return\n");
  puts("> bool retFunction() should return true...");
  bret=functor.invokeR();
  printf("Returned: %d\n", bret);
  puts("> char* retFunction(5) should return \"Hello\"...");
  cret=functor1.invokeR(5);
  printf("Returned: %s\n", cret);
  puts("> double retFunction(true, \"argument 1\") should return 4.62...");
  dret=functor2.invokeR(true, "argument 1");
  printf("Returned: %e\n", dret);
}
// Invocation of pointers which supply the parameter type. Full invocation
// with paramters is posesible in this fashion with out knowing the class
// that the functor refers to.
void testGlobalParams()
{
  ArGlobalFunctor functor(function);
  ArGlobalFunctor1<int> functor1(function, 1);
  ArGlobalFunctor2<bool, std::string> functor2(function, false,
						"default arg");
  ArFunctor *fptr;
  ArFunctor1<int> *fptr1;
  ArFunctor2<bool, std::string> *fptr2;

  printf("\n****** Testing global pointer invocation\n");
  fptr=&functor;
  puts("> Should see function()...");
  fptr->invoke();
  fptr1=&functor1;
  puts("> Should see function(2)...");
  fptr1->invoke(2);
  fptr2=&functor2;
  puts("> Should see function(true, \"argument 2\")...");
  fptr2->invoke(true, "argument 2");
}
// Invocation of a base ArFunctor pointer to a functor. Because the pointer
// is of type ArFunctor, the parameters can not be supplied. The default
// parameters, which are supplied when the functor is constructed, are used.
void testBase()
{
  TestClass test;
  ArFunctor *fptr;
  ArFunctorC<TestClass> functor(test, &TestClass::function);
  ArFunctor1C<TestClass, int> functor1(test, &TestClass::function, 1);
  ArFunctor2C<TestClass, bool, std::string> functor2(test,
						     &TestClass::function,
						     false, "default arg");

  printf("\n****** Testing base invocation\n");
  fptr=&functor;
  puts("> Should see TestClass::function()...");
  fptr->invoke();
  fptr=&functor1;
  puts("> Should see TestClass::function(1)...");
  fptr->invoke();
  fptr=&functor2;
  puts("> Should see TestClass::function(false, \"default arg\")...");
  fptr->invoke();
}
int main()
{
  CallbackClass cb;


  // For functors with no arguments:
  std::list<ArFunctor*> functors;
  ArFunctorC<CallbackClass> functor1(cb, &CallbackClass::callback1);
  functors.push_back(&functor1);
  functors.push_back(&functor1);
  functors.push_back(&functor1);
  std::for_each(functors.begin(), functors.end(), 
      std::mem_fun(&ArFunctor::invoke));

  // For functors with arguments, give mem_fun template parameters.
  std::list<ArFunctor1<int>*> functorsWithArg;
  ArFunctor1C<CallbackClass, int> functor2(cb, &CallbackClass::callback2);
  std::mem_fun1_t<void, ArFunctor1<int>, int> f(&ArFunctor1<int>::invoke);
  functorsWithArg.push_back(&functor2);
  functorsWithArg.push_back(&functor2);
  functorsWithArg.push_back(&functor2);
  std::for_each(functorsWithArg.begin(), functorsWithArg.end(), std::bind2nd(f, 42));

  // You can use other STL algorithms if your functor returns something.
  // count_if will invoke each functor, and return the number of functor
  // invocations that returned true (in this case, 3, since they will 
  // always return true)
  std::list<ArRetFunctor1<bool, const char*>*> functorsWithRet;
  ArRetFunctor1C<bool, CallbackClass, const char *>
    functor3(cb, &CallbackClass::callback3);
  std::mem_fun1_t<bool, ArRetFunctor1<bool, const char*>, const char*> rf(&ArRetFunctor1<bool, const char*>::invokeR);
  functorsWithRet.push_back(&functor3);
  functorsWithRet.push_back(&functor3);
  functorsWithRet.push_back(&functor3);
  int c = std::count_if(functorsWithRet.begin(), functorsWithRet.end(), std::bind2nd(rf, "testing"));
  std::cout << "Count=" << c << std::endl;

  return(0);
}
// Invocation of pointers which supply the parameter type. Full invocation
// with paramters is posesible in this fashion with out knowing the class
// that the functor refers to.
void testParams()
{
  TestClass test;
  ArFunctorC<TestClass> functor(test, &TestClass::function);
  ArFunctor1C<TestClass, int> functor1(test, &TestClass::function);
  ArFunctor2C<TestClass, bool, std::string> functor2(test,
						     &TestClass::function);
  ArFunctor *fptr;
  ArFunctor1<int> *fptr1;
  ArFunctor2<bool, std::string> *fptr2;

  printf("\n****** Testing pointer invocation\n");
  fptr=&functor;
  puts("> Should see TestClass::function()...");
  fptr->invoke();
  fptr1=&functor1;
  puts("> Should see TestClass::function(2)...");
  fptr1->invoke(2);
  fptr2=&functor2;
  puts("> Should see TestClass::function(true, \"argument 2\")...");
  fptr2->invoke(true, "argument 2");
}
int main()
{
  CallbackContainer cb;
  DriverClass driver;

  ArFunctorC<CallbackContainer> functor1(cb, &CallbackContainer::callback1);
  ArFunctor1C<CallbackContainer, int> functor2(cb, &CallbackContainer::callback2);
  ArRetFunctor1C<bool, CallbackContainer, const char *>
    functor3(cb, &CallbackContainer::callback3);

  driver.setCallback1(&functor1);
  driver.setCallback2(&functor2);
  driver.setCallback3(&functor3);

  driver.invokeFunctors();

  /* You can make functors that target global functions too. */
  ArGlobalFunctor globalFunctor(&globalCallback);
  printf("Invoking globalFunctor... ");
  globalFunctor.invoke();

  /* You can also include the values of arguments in an ArFunctor object, if you
   * want to use the same value in every invocation of the functor.
   */
  ArFunctor1C<CallbackContainer, int> functor4(cb, &CallbackContainer::callback2, 42);
  printf("Invoking functor with constant argument... ");
  functor4.invoke();

  /* Functors can be downcast to parent interface classes, as long as their invocation
   * does not require arguments.
   */
  ArFunctor* baseFunctor = &functor4;
  printf("Invoking downcast functor... ");
  baseFunctor->invoke();


  return(0);
}