xref: /llvm-project/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp (revision b41e2d92982b1f3f1961db479a9d2a8801f71477)
1 // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
2 
3 // Example function implementation from the variadic templates proposal,
4 // ISO C++ committee document number N2080.
5 
6 template<typename Signature> class function;
7 
8 template<typename R, typename... Args> class invoker_base {
9 public:
10   virtual ~invoker_base() { }
11   virtual R invoke(Args...) = 0;
12   virtual invoker_base* clone() = 0;
13 };
14 
15 template<typename F, typename R, typename... Args>
16 class functor_invoker : public invoker_base<R, Args...> {
17 public:
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 
22 private:
23   F f;
24 };
25 
26 template<typename R, typename... Args>
27 class function<R (Args...)> {
28 public:
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 
66 private:
67   invoker_base<R, Args...>* invoker;
68 };
69 
70 template<typename T>
71 struct add {
72   T operator()(T x, T y) { return x + y; }
73 };
74 
75 int add_ints(int x, int y) { return x + y; }
76 
77 void 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