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