initial code
This commit is contained in:
commit
0fa524693b
3 changed files with 224 additions and 0 deletions
121
crtp_functor_ttp.cpp
Normal file
121
crtp_functor_ttp.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#define ITEMS(c) c.begin(),c.end()
|
||||||
|
|
||||||
|
// remains inchanged
|
||||||
|
template<class T>
|
||||||
|
class Increment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T arg;
|
||||||
|
Increment( T a ) : arg(a) {}
|
||||||
|
|
||||||
|
template<typename OutIt>
|
||||||
|
T operator() ( T & value, OutIt out )
|
||||||
|
{
|
||||||
|
value+=arg;
|
||||||
|
*out++ = value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* We want to be able to use the functor interface as a templated class.
|
||||||
|
* But, it takes the derived class as a template parameter,
|
||||||
|
* along with the type of an operator class, which is templated:
|
||||||
|
* both of which are templated themselves.
|
||||||
|
*
|
||||||
|
* We want to avoid having to use declarations of the form:
|
||||||
|
* Functor<Assign<Increment<T>,T>,Increment<T>,T>
|
||||||
|
* Thus the complicated template of template (of template) structures below, which permits to write:
|
||||||
|
* Functor<Assign,Increment,T>
|
||||||
|
*
|
||||||
|
* Below, "typename" is used where a standard type (being fundamentals or in the STL) is expected,
|
||||||
|
* and "class" where a class from the framework is expected.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
// The templates structure of the derived class
|
||||||
|
template<
|
||||||
|
// An operator, i.e. a class with a template <=> a template of template
|
||||||
|
template<typename> class,
|
||||||
|
// A type
|
||||||
|
typename
|
||||||
|
// used as a type called CRTP
|
||||||
|
> class CRTP,
|
||||||
|
|
||||||
|
// The template structure of the operator <=> a template of template called OP
|
||||||
|
template<typename> class OP,
|
||||||
|
|
||||||
|
// the simple value type
|
||||||
|
typename T
|
||||||
|
>
|
||||||
|
class Functor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OP<T> & op;
|
||||||
|
Functor( OP<T> & o ) : op(o) {}
|
||||||
|
|
||||||
|
// the function is not virtual, we can put a template on it
|
||||||
|
template<typename OutIt>
|
||||||
|
int operator() ( int& v, OutIt out )
|
||||||
|
{
|
||||||
|
return static_cast<CRTP<OP,T>*>(this)->functor(v,out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instead of having to write:
|
||||||
|
* Assign<Increment,int> f(op);
|
||||||
|
* We can just write:
|
||||||
|
* auto f = make<Assign>(op);
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
template< template<typename> class, typename > class FC,
|
||||||
|
template <typename> class OP,
|
||||||
|
typename T
|
||||||
|
>
|
||||||
|
FC<OP,T>& make_Functor( OP<T> & op )
|
||||||
|
{
|
||||||
|
return *(new FC<OP,T>(op));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inherits from Functor via the CRTP
|
||||||
|
template<template <typename> class OP, class T>
|
||||||
|
class Assign : public Functor<Assign,OP,T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Assign( OP<T> & o ) : Functor<Assign,OP,T>(o) {}
|
||||||
|
|
||||||
|
template<typename OutIt>
|
||||||
|
inline int functor( int& value, OutIt out )
|
||||||
|
{
|
||||||
|
// std::clog << value << " + " << this->op.arg << std::endl;
|
||||||
|
return this->op(value,out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
size_t nb = 10000;
|
||||||
|
|
||||||
|
for( unsigned int k=0; k<nb; ++k) {
|
||||||
|
std::vector<int> v;
|
||||||
|
auto out = std::back_inserter(v);
|
||||||
|
|
||||||
|
Increment<int> add_one(1);
|
||||||
|
|
||||||
|
auto f = make_Functor<Assign>(add_one);
|
||||||
|
|
||||||
|
int i = -1;
|
||||||
|
size_t n = 0;
|
||||||
|
for( unsigned int j=0; j<nb; ++j ) {
|
||||||
|
n += f(i, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cout << v.size() << std::endl;
|
||||||
|
// std::copy( ITEMS(v), std::ostream_iterator<int>( std::cout, "\n") );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
91
inheritance_functor.cpp
Normal file
91
inheritance_functor.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#define ITEMS(c) c.begin(),c.end()
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class Increment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T arg;
|
||||||
|
Increment( T a ) : arg(a) {}
|
||||||
|
|
||||||
|
template<typename OutIt>
|
||||||
|
T operator() ( T& value, OutIt out )
|
||||||
|
{
|
||||||
|
value+=arg;
|
||||||
|
*out++ = value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class OP, typename OutIt>
|
||||||
|
class Functor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OP & op;
|
||||||
|
Functor( OP & o ) : op(o) {}
|
||||||
|
|
||||||
|
// we cannot put the OutIt template here, because the functor is virtual
|
||||||
|
virtual int operator() ( int& v, OutIt out ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* It is painfull to declare a Functor's derivate class with all the templates
|
||||||
|
* because C++ can't infer templates from parameters of the constructor.
|
||||||
|
* Thus, we rely on this helper free function, where templates can be infered.
|
||||||
|
*
|
||||||
|
* Instead of having to write:
|
||||||
|
* Assign<Increment<int>, std::back_insert_iterator<std::vector<int> > > f(add_one);
|
||||||
|
* We can just write:
|
||||||
|
* auto f = make_Functor<Assign>( add_one, std::back_inserter(v));
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
template< class, typename > class FC,
|
||||||
|
class OP,
|
||||||
|
typename OutIt
|
||||||
|
>
|
||||||
|
FC<OP,OutIt>& make_Functor( OP & op, OutIt /*out*/ )
|
||||||
|
{
|
||||||
|
return *(new FC<OP,OutIt>(op));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class OP, typename OutIt>
|
||||||
|
class Assign : public Functor<OP, OutIt>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Assign( OP & o ) : Functor<OP, OutIt>(o) {}
|
||||||
|
|
||||||
|
int operator() ( int& value, OutIt out )
|
||||||
|
{
|
||||||
|
// std::clog << value << " + " << this->op.arg << std::endl;
|
||||||
|
return this->op(value,out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
size_t nb = 10000;
|
||||||
|
|
||||||
|
for( unsigned int k=0; k<nb; ++k) {
|
||||||
|
std::vector<int> v;
|
||||||
|
auto out = std::back_inserter(v);
|
||||||
|
|
||||||
|
Increment<int> add_one(1);
|
||||||
|
|
||||||
|
// we specify the output iterator here, just for type inference
|
||||||
|
auto f = make_Functor<Assign>(add_one, out);
|
||||||
|
|
||||||
|
int i = -1;
|
||||||
|
size_t n = 0;
|
||||||
|
for( unsigned int j=0; j<nb; ++j ) {
|
||||||
|
n += f(i, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cout << v.size() << std::endl;
|
||||||
|
// std::copy( ITEMS(v), std::ostream_iterator<int>( std::cout, "\n") );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12
test.sh
Executable file
12
test.sh
Executable file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cmd="g++ -O3 -std=c++0x "
|
||||||
|
$cmd inheritance_functor.cpp -o inheritance_functor
|
||||||
|
echo "inheritance_functor"
|
||||||
|
time ./inheritance_functor
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "crtp_functor_ttp"
|
||||||
|
$cmd crtp_functor_ttp.cpp -o crtp_functor_ttp
|
||||||
|
time ./crtp_functor_ttp
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue