bevált c++ technikák 2007.12.10. budapest. tartalom funktor, boost.{bind, lambda} static assert...
TRANSCRIPT
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Fabejárás
template<class Data>struct Tree {
Tree* left;Tree* right;Data* data;
};
template<class Data>void preorder(Tree<Data>* tree){
if (tree->data)[process *tree->data]
if (tree->left)preorder(tree->left);
if (tree->right)preorder(tree->right);
}
1. void printData(Data&);2. class MyClass {
// …void processData(Data&);
} myClass;
3. void printData2(Data&, int param);4. class MyClass {
// …void processData2(Data&, int);
} myClass;
Fabejárás, függvénypointer
1. void printData(Data&);2. class MyClass {
// …void processData(Data&);
} myClass;
3. void printData(Data&, int param);4. class MyClass {
// …void processData(Data&, int);
} myClass;
template<class Data>void preorder(Tree<Data>* tree, void (*f)(Data&)){
if (tree->data)(*f)(*tree->data);
if (tree->left)preorder(tree->left, f);
if (tree->right)preorder(tree->right, f);
}
Fabejárás, STL funktor
Hátrány: mindig új típust (osztályt) kell létrehozni egy operator()(Data&) művelettel
template<class Data, class Functor>void preorder(Tree<Data>* tree, Functor f){
if (tree->data)f(*tree->data);
if (tree->left)preorder(tree->left, f);
if (tree->right)preorder(tree->right, f);
}
struct printDataFunctor { void operator()(Data& d) { printData(d); }};
Boost.bind
Tree<std::string> szavak;
preorder(&szavak, boost::bind(&printData, _1));
preorder(&szavak, boost::bind(&MyClass::processData, &myClass, _1));
preorder(&szavak, boost::bind(&printData2, _1, 5));
preorder(&szavak, boost::bind(&MyClass::processData2, &myClass, _1, 5));
struct X { std::string name };
std::find_if(first, last, bind(&X::name, _1) == "peter");
std::sort(first, last, bind(&X::name, _1) < bind(&X::name, _2));
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Static asserttemplate<bool condition>
class StaticAssert;
template<>
class StaticAssert<true> {};
template<int size>
class Array
{
public:
char data[1 << size];
StaticAssert<size<10> sizeConstraint;
};
Array<8> array8; // ok
Array<10> array10; // error
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Boost.spirit, calculatorgroup ::= '(' expression ')‘factor ::= integer | groupterm ::= factor (('*' factor) | ('/' factor))*expression ::= term (('+' term) | ('-' term))*
(-1 + 2) * (3 + -4)1 + ((6 * 200) - 20) / 6
struct calculator : public grammar<calculator> {template <typename ScannerT> struct definition {
definition(calculator const& self) {group = '(' >> expression >> ')';factor = integer | group;term = factor >> *(('*' >> factor) | ('/' >> factor));expression = term >> *(('+' >> term) | ('-' >> term));
}rule<ScannerT> expression, term, factor, group;rule<ScannerT> const& start() const { return expression; }
};};
Boost.spirit, actionsvoid do_int(char const* str, char const* end);
void do_add(char const*, char const*);
void do_subt(char const*, char const*);
void do_mult(char const*, char const*);
void do_div(char const*, char const*);
void do_neg(char const*, char const*);
expression = term >> *( ('+' >> term)[&do_add] | ('-' >> term)[&do_subt] ) ;
term = factor >> *( ('*' >> factor)[&do_mult] | ('/' >> factor)[&do_div] ) ;
factor = lexeme_d[(+digit_p)[&do_int]] | '(' >> expression >> ')' |('-' >> factor)[&do_neg] | ('+' >> factor) ;
DSEL – Domain Specific Embedded Language
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Template metaprogrammingtemplate <int N>class Factorial{public:
enum { value = N*Factorial<N-1>::value };};
template<>class Factorial<1>{public:
enum { value = 1 };};
int main (){
return Factorial<5>::value;}
Template metaprogramming (2)// accumulate(n,f) := f(0) + f(1) + ... + f(n)template <int n, template<int> class F>struct Accumulate{
enum { RET=Accumulate<n-1,F>::RET+F<n>::RET };};template<template<int> class F>struct Accumulate<0,F>{
enum { RET = F<0>::RET };};template <int n>struct Square{
enum { RET = n*n };};int main(){
return Accumulate<3,Square>::RET; // 0^2 + 1^2 + 2^2 + 3^2 = 14}
Type liststruct Null {};
template<class H = Null, class T = Null>
struct TList {
typedef H Head;
typedef T Tail;
};
typedef TList<short, TList<int, TList<long> > > integral_types;
template<class Type> struct TListCount;
template<class H, class T> struct TListCount<TList<H,T> > {
enum { Result = 1 + TListCount<T>::Result };
};
template<> struct TListCount<Null> { enum { Result = 0 }; };
const int n = TListCount<integral_types>::Result; // 3
Generated class hierarchytemplate<class List> struct Hierarchy;
template<class H, class T> struct Hierarchy<TList<H,T> > :
public H, public Hierarchy<T> {};
template<> struct Hierarchy<Null> {};
Hierarchy<TList<A,TList<B,TList<C> > > >
template<class List, template<class> Base> struct Hierarchy2;
template<class H, class T, template<class> Base>
struct Hierarchy2<TList<H,T>, Base> :
public Base<H>, public Hierarchy<T, Base> {};
template<template<class> Base> struct Hierarchy2<Null, Base> {};
A
B
C
Base<A>
Base<B>
Base<C>
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Boost.preprocessor
#define TLIST_OP(s,x,h) TList<h,
#define ENDBRACKET(item, n, data) >
#define TLIST(t) \
BOOST_PP_SEQ_FOR_EACH(TLIST_OP, x, t) Null \ BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(t), ENDBRACKET, data)
typedef TLIST((short)(int)(long)) integrals;
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Concepts
template<Forward_iterator Fwd, class T>
where Assignable<Fwd::value_type,T>
void fill(Fwd first, Fwd last, const T& t);
concept Assignable<typename T, typename U = T> {
Var<T> a;
Var<const U> b;
a = b;
};
assert Assignable<vector<int> >;
Tartalom
• Funktor, boost.{bind, lambda}
• Static assert
• Boost.spirit
• Template metaprogramming
• Preprocessor metaprogramming
• Concepts
• Irodalom, contact
Irodalom, contactA.Alexandrescu: Modern C++ Design
D.Abrahams, A.Gurtovoy: C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond
Boost libraries: http://www.boost.org
Specifying C++ concepts: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1886.pdf
Mihalicza József
mailto:[email protected]