1// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 2 3// Example function implementation from the variadic templates proposal, 4// ISO C++ committee document number N2080. 5 6template<typename Signature> class function; 7 8template<typename R, typename... Args> class invoker_base { 9public: 10 virtual ~invoker_base() { } 11 virtual R invoke(Args...) = 0; 12 virtual invoker_base* clone() = 0; 13}; 14 15template<typename F, typename R, typename... Args> 16class functor_invoker : public invoker_base<R, Args...> { 17public: 18 explicit functor_invoker(const F& f) : f(f) { } 19 R invoke(Args... args) { return f(args...); } 20 functor_invoker* clone() { return new functor_invoker(f); } 21 22private: 23 F f; 24}; 25 26template<typename R, typename... Args> 27class function<R (Args...)> { 28public: 29 typedef R result_type; 30 function() : invoker (0) { } 31 function(const function& other) : invoker(0) { 32 if (other.invoker) 33 invoker = other.invoker->clone(); 34 } 35 36 template<typename F> function(const F& f) : invoker(0) { 37 invoker = new functor_invoker<F, R, Args...>(f); 38 } 39 40 ~function() { 41 if (invoker) 42 delete invoker; 43 } 44 45 function& operator=(const function& other) { 46 function(other).swap(*this); 47 return *this; 48 } 49 50 template<typename F> 51 function& operator=(const F& f) { 52 function(f).swap(*this); 53 return *this; 54 } 55 56 void swap(function& other) { 57 invoker_base<R, Args...>* tmp = invoker; 58 invoker = other.invoker; 59 other.invoker = tmp; 60 } 61 62 result_type operator()(Args... args) const { 63 return invoker->invoke(args...); 64 } 65 66private: 67 invoker_base<R, Args...>* invoker; 68}; 69 70template<typename T> 71struct add { 72 T operator()(T x, T y) { return x + y; } 73}; 74 75int add_ints(int x, int y) { return x + y; } 76 77void test_function() { 78 function<int(int, int)> f2a; 79 function<int(int, int)> f2b = add<int>(); 80 function<int(int, int)> f2c = add<float>(); 81 function<int(int, int)> f2d(f2b); 82 function<int(int, int)> f2e = &add_ints; 83 f2c = f2d; 84 f2d = &add_ints; 85 f2c(1.0, 3); 86} 87