22
Bevált C++ technikák 2007.12.10. Budapest

Bevált C++ technikák 2007.12.10. Budapest. Tartalom Funktor, boost.{bind, lambda} Static assert Boost.spirit Template metaprogramming Preprocessor metaprogramming

Embed Size (px)

Citation preview

Bevált C++ technikák

2007.12.10.Budapest

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]