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