Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++ Templates: More Powerful Than You Think

Similar presentations


Presentation on theme: "C++ Templates: More Powerful Than You Think"— Presentation transcript:

1 C++ Templates: More Powerful Than You Think

2 template <typename T> class allocator;
Class Templates template <typename T> class allocator; template <typename T, typename Alloc = allocator<T>> class list { }; template <typename T> class shared_ptr { public: typedef T *pointer; typedef T &reference; reference operator*() const {return *px;} pointer operator->() const {return px;} private: T *px;

3 Function Templates template <typename T> inline void swap(T &a, T &b) { T tmp (a); a = b; b = tmp; } template <typename T> inline const T &max(const T &a, const T &b) { if (a < b) return b; return a; template <typename Iter> void sort(Iter first, Iter last) { // ... some sort algorithm ...

4 Method Templates template <typename T> class shared_ptr { public: shared_ptr &operator=(const shared_ptr &r) { } template <typename Y> shared_ptr &operator=(const shared_ptr<Y> &r) { };

5 Constructor Templates
template <typename T> class shared_ptr { public: shared_ptr (const shared_ptr &r) { } template <typename Y> shared_ptr (const shared_ptr<Y> &r) { };

6 C++11: Template Aliases template <typename T> using Ptr = T *; template <typename T, typename... Args> using Func = T(Args...); using SigHandler = Ptr<Func<void, int>>; class MyAllocator { … }; template <typename T> using MyList = std::list<T, MyAllocator>; using MyVector = std::vector<T, MyAllocator>;

7 Non-Type Template Parameters
template <typename T, unsigned int N> class array { private: T elems[N]; public: T &operator[](unsigned int i) {return elems[i];} const T &operator[](unsigned int i) const {return elems[i];} };

8 Template Template Parameters
template <typename T> class Deque { … }; template <typename T> class List { … }; template <typename T, template <typename> class Container = Deque> class Stack { }; Stack<int> s1; Stack<std::string, List> s2;

9 Explicit Specialisations
template <typename T> class MyList { }; // Specialisation for void pointers template <> class MyList<void *> { // Partial specialisation for all other pointers template <typename T> class MyList<T *>: public MyList<void *> {

10 Implicit Specialisations
class A { … }; class B: public A { … }; shared_ptr<A> pa1; // Generates a new class: shared_ptr<A> shared_ptr<A> pa2; // Uses the same class: shared_ptr<A> shared_ptr<B> pb; // Generates a completely different class: shared_ptr<B> int m, n; swap(m, n); // Generates swap<int>(const int &, const int &) swap(pa1, pa2); // ... swap<shared_ptr<A>>(const shared_ptr<A> &, const shared_ptr<A> &) pa1 = pa2; // Uses shared_ptr<A>::operator=(const shared_ptr &) generated above pa2 = pb; // Generates shared_ptr<A>::operator=<B>(const shared_ptr<B> &) shared_ptr<A> pa3(pa1); // Uses shared_ptr<A>::shared_ptr(const shared_ptr &) shared_ptr<A> pa4(pb); // Generates shared_ptr<A>::shared_ptr<B> (const shared_ptr<B> &)

11 Substitution Failure Is Not An Error
struct Test { typedef int type; }; template <typename T> void f(typename T::type) {} // definition #1 template <typename T> void f(T) {} // definition #2 void foo() { f<Test>(10); //call #1 f<int>(10); //call #2 without error thanks to SFINAE }

12 Metafunctions #include <iostream> template <unsigned int N> struct Factorial { static const unsigned long long value = N * Factorial<N – 1>::value; }; template <> struct Factorial<0> { static const unsigned long long value = 1; int main () { std::cout << "Factorial of 10 is " << Factorial<10>::value << std::endl; return 0; }

13 Metafunctions Working With Types
template <bool C, typename T1, typename T2> struct if_c { typedef T1 type; }; template <typename T1, typename T2> struct if_c<false, T1, T2> { typedef T2 type; template <typename T> struct MyListNode { typedef if_c<(sizeof(T) > sizeof(int)), T *, T>::type ValueType; Node *prev; Node *next; ValueType value;

14 Using Type Wrappers To Select Algorithm
template <bool C> struct bool_ { static const bool value = C; typedef bool_ type; }; template <typename C, typename T1, typename T2> using if_ = if_c<C::value, T1, T2>; template <typename T> struct MyListNode { using UsePointer = bool_<(sizeof(T) > sizeof(int))>; using ValueType = if_<UsePointer, T *, T>::type; static const T &make_value(const T &v, bool_<false>) {return v;} static T *make_value(const T &v, bool_<true>) {return new T(v);} MyListNode(const T &v): value(make_value(val, UsePointer())) {}

15 Using SFINAE To Select Algorithm
template <bool B, typename T = void> struct enable_if_c {typedef T type;}; template <typename T> struct enable_if_c<false, T> {}; template <typename C, typename T = void> using enable_if = enable_if_c<C::value, T>; template <typename C> using not_ = bool_<!C::value>; template <typename T> struct MyListNode { using UsePointer = bool_<(sizeof(T) > sizeof(int))>; using ValueType = if_<UsePointer, T *, T>::type; MyListNode(enable_if<UsePointer, const T &>::type): value(v) {} MyListNode(enable_if<(not_<UsePointer>, const T &>::type): value(new T(v)) {} };

16 Boost.MPL: Factorial Example
#include <iostream> #include <boost/mpl/if.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/prior.hpp> #include <boost/mpl/times.hpp> #include <boost/mpl/equal_to.hpp> using boost::mpl; template <typename N> struct Factorial: if_<equal_to<N, int_<0>>, int_<1>, times<N, Factorial<typename N::prior>>>::type {}; int main () { std::cout << "Factorial of 10 is " << Factorial<int_<10>>::value << std::endl; return 0; }

17 Boost.MPL: Searching In Type Sequences
#include <iostream> #include <boost/mpl/bool.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/contains.hpp> using signed_types = boost::mpl::vector<signed char, short, int, long, long long>; template <typename T> using is_signed = boost::mpl::contains<signed_types, T>; constexpr const char *signed_str(boost::mpl::true_) {return "signed";} constexpr const char *signed_str(boost::mpl::false_) {return "not signed";} int main () { std::cout << "int is " << signed_str(is_signed<int>()) << "\n"; std::cout << "unsigned int is " << signed_str(is_signed<unsigned int>()) << "\n"; return 0; }

18 Boost.MPL: Folding Type Sequences
template <typename T> struct mytuple_field {T field;}; using mytuple_types = boost::mpl::vector<int, const char *, bool>; using mytuple = boost::mpl::fold<mytuple_types, boost::mpl::empty_base, boost::mpl::inherit<boost::mpl::_1, mytuple_field<boost::mpl::_2>>>::type; template <typename T> inline T &field(mytuple_field<T> &t) {return t.field;} int main () { mytuple t; field<int>(t) = -1; field<const char *>(t) = "text"; field<bool>(t) = false; std::cout << field<int>(t) << '\n' << field<const char *>(t) << '\n' << field<bool>(t) << '\n'; return 0; }

19 Questions?


Download ppt "C++ Templates: More Powerful Than You Think"

Similar presentations


Ads by Google