Esempio di polymorphic function wrappers (C++0x)…
E’ un periodo in cui sono in vena di sperimentazione, per cui proseguiamo il discorso sulle nuove feature dello standard C++0x: è il turno dei wrapper polimorfici e delle nuove map di tipo unordered.
Nell’esempietto che vi propongo sfrutteremo i wrapper polimorfici di funzione (classe “function”) per estendere gli oggetti di una classe (Extendable) a runtime: in altri termini inietteremo delle funzioni nella classe (una forma di dependency injection, “Type 2″) per poi richiamarle in un secondo tempo.
Le funzioni iniettate verranno inserite in una “unordered map“, una struttura meglio nota come array associativo non ordinato o anche “hash map“, che rappresenta una novità per la Standard Template Library (STL) del C++.
Spero che l’esempio sia sufficientemente chiaro!
Ciau!
/**
* FILE : PolyWrapperExample.cpp
* AUTHOR : Gian Paolo "JP" Ghilardi (http://rejex.wordpress.com)
* LICENSE : released under the terms of GPL v2.0 ("only")
* COMPILE : g++ -Wall -Winline -pedantic -std=c++0x
* PolyWrapperExample.cpp -o PolyWrapperExample
* PURPOSE : simple C++0x example showing C++0x polymorphous wrappers
* for function objects [2], rvalue parameters [3] and
* an unordered map [4] in action
*
* TESTED ON :
* - Windows XP, x86 32-bit, G++ 4.4.0
*
* REFERENCES:
* [1]: http://en.wikipedia.org/wiki/Dependency_injection
* [2]: http://en.wikipedia.org/wiki/C%2B%2B0x#Polymorphous_wrappers_for_function_objects
* [3]: http://en.wikipedia.org/wiki/C%2B%2B0x#Rvalue_reference_and_move_semantics
* [4]: http://en.wikipedia.org/wiki/C%2B%2B0x#Hash_tables
* [5]: http://en.wikipedia.org/wiki/Unordered_map_(C%2B%2B_class)
*/
#ifdef __STRICT_ANSI__ // to avoid a MinGW G++ 4.4.0 bug ("swprintf undeclared...")
#undef __STRICT_ANSI__
#include <cstdlib>
#include <iostream>
#define __STRICT_ANSI__
#else
#include <cstdlib>
#include <iostream>
#endif
#include <functional>
#include <string>
#include <unordered_map>
using namespace std;
// this class allows to "inject" and save function objects
// to be executed later (dependency injection, type 2 [1])
class Extendable
{
typedef function<void (void)> fwrapper;
public:
// save a wrapper function in the unordered map
inline void inject(const string &&alias, const fwrapper &&fwrap)
{
injected_.insert(make_pair(alias, fwrap));
}
// used to call a registered ("injected") function object
inline void callByName(const string &&s)
{
if(injected_.find(s) != injected_.end())
injected_[s]();
else
cout << "- Error: function '" << s << "' does not exist!" << endl;
}
// used to call a registered ("injected") function object
inline void operator[](const string &&s)
{
callByName(s);
}
private:
unordered_map<string, fwrapper> injected_; // [4, 5]
};
// simple function to be bound to a function object
// Note: this function could be replaced with a in-place lambda expression.
// Unfortunately at the moment G++ does not support them.
inline void testFunc()
{
cout << "- testFunc() here!" << endl;
}
int main(int argc, char **argv)
{
cout << "C++0x EXAMPLE:" << endl;
cout << "Simple example showing some C++0x features" << endl << endl;
Extendable e;
e.inject("ok", testFunc); // add the function with an alias (dependency injection)
// Note: implicit function->fwrapper conversion
e["ok"]; // ok, prints "testFunc() here!"
e["error"]; // error, prints "Error: function 'error' does not exist!"
e.callByName("ok"); // ok, prints "testFunc() here!"
return EXIT_SUCCESS;
}

Commenti Recenti