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