MyDataClass & foo()
{
static MyDataClass data;
// Do some work
return data;
}
MyDataClass & foo(Mutex m)
{
ScopedLock sl(m); // Ensure no other thread can get in here
static MyDataClass data;
// Do some work
return data;
// Note once the scoped lock ends here another thread could enter
// and modify data before the caller has a chance to copy it
// so even this isn't a very good solution, really the mutex should
// be locked by the caller.
}
void callback_func(void *){}
void callback_func(char *){}
template <typename funcT>
void consumer(funcT callback_func)
{}
int main()
{
consumer(callback_func); // ERROR: Which one?
consumer((void (*)(void*))callback_func);
consumer((void (*)(char*))callback_func);
}
bool third_party_func(int, char, float){ return true; }
template <typename funcT>
void invoker(funcT callback_func)
{
callback_func(int());
}
// C style adaptors
void adaptor_func1(int n)
{
third_party_func(n, 'c', 1.1f); // Hard coded bindings, cannot be changed at runtime
}
void adaptor_func2(int n)
{
third_party_func(n, 'b', 5.9f); // Hard coded bindings, cannot be changed at runtime
}
int main()
{
// C style function has hard coded bindings
invoker(adaptor_func1);
invoker(adaptor_func2);
}
class Functor
{
public:
R operator()(T1, ..., Tn)
{
return R();
}
};
class LessThanFunctor
{
public:
bool operator()(int lhs, int rhs)
{
return lhs < rhs;
}
};
bool third_party_func(int, char, float){ return true; }
template <typename funcT>
void invoker(funcT callback_func)
{
callback_func(int());
}
// C++ style adaptor
class adaptor_functor
{
public:
// Initialize runtime bindings
adaptor_functor(char cb, float fb) : cb_(cb), fb_(fb){}
void operator()(int n)
{
third_party_func(cb_, fb_, n);
}
private:
char cb_;
float fb_;
};
int main()
{
// C++ functor has bindings that can be set ar runtime via the functors constructor
invoker(adaptor_functor('a', 2.3f));
invoker(adaptor_functor('z', 0.0f));
}
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
// Note that this logging class assumes single threading, additional code would be required
// to provide mutual exclusion semantics, which are outside the scope of this article
class LoggingFunctor
{
public:
// Constructor allows user defined output stream
LoggingFunctor(std::ostream & os) :
os_(os), nErrCnt_(0), nLogCnt_(0) {}
// Overload for std::string
void operator()(std::string const & s, bool bErr)
{
// Hand off to overload for char const *
(*this)(s.c_str(), bErr);
}
// The main logging funcion
void operator()(char const * szMsg, bool bErr)
{
// Count log item
++ nLogCnt_;
// Display date & time
time_t t = time(0);
char tbuf[80];
strftime (tbuf,80,"%x %X ",localtime(&t));
os_ << tbuf;
// Is this an error message?
if(bErr)
{
// Count error and display error prefix
++ nErrCnt_;
os_ << "ERROR: ";
}
// NOw log it
os_ << szMsg << std::endl;
}
// Accessors to the log and error count
int GetErrCnt() const { return nErrCnt_; }
int GetLogCnt() const { return nLogCnt_; }
private:
// Non-copyable semantics to prevent accidental copy or assignment
LoggingFunctor(LoggingFunctor const &);
LoggingFunctor operator=(LoggingFunctor const &);
private:
std::ostream & os_;
int nErrCnt_;
int nLogCnt_;
};
template <typename LoggingFunctorT>
void Mock3rdPartyCall(LoggingFunctorT & logger)
{
for(int i = 0 ; i < 25; ++i)
{
// Build a log message
std::stringstream ss;
ss << "Log entry " << i;
// Log it, treat every 3rd iteration as an error
logger(ss.str(), i%3 == 0);
}
}
int main()
{
// Log to stdout for this example
LoggingFunctor loggingFunctor(std::cout);
// Call the mock 3rd party function
Mock3rdPartyCall(loggingFunctor);
std::cout
<< std::endl
<< loggingFunctor.GetLogCnt() << " items logged, "
<< loggingFunctor.GetErrCnt() << " of which were errors." << std::endl;
}
#include <iostream>
class LessThanFunctor
{
public:
bool operator()(int lhs, int rhs)
{
return lhs < rhs;
}
};
bool LessThanFunction(int lhs, int rhs)
{
return lhs < rhs;
}
// To make this work with a function or functor we just use a template parameter
template <typename functorT>
bool Invoker(functorT func, int x, int y)
{
return func(x,y);
}
int main()
{
std::cout
<< "Functor: " << Invoker(LessThanFunctor(), 5, 6)
<< std::endl
<< "Function: " << Invoker(LessThanFunction, 5, 6)
<< std::endl
<< "Functor: " << Invoker(LessThanFunctor(), 7, 6)
<< std::endl
<< "Function: " << Invoker(LessThanFunction, 7, 6)
<< std::endl;
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (1)
Commented: