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