111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                     The LLVM Compiler Infrastructure
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details.
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// <functional>
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// template<Returnable R, CopyConstructible... ArgTypes>
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// class function<R(ArgTypes...)> {
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// public:
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   typedef R result_type;
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   typedef T1 argument_type;          // iff sizeof...(ArgTypes) == 1 and
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                      // the type in ArgTypes is T1
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   typedef T1 first_argument_type;    // iff sizeof...(ArgTypes) == 2 and
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                      // ArgTypes contains T1 and T2
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//   typedef T2 second_argument_type;   // iff sizeof...(ArgTypes) == 2 and
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                      // ArgTypes contains T1 and T2
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//  ...
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//  };
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <functional>
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <type_traits>
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename T>
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass has_argument_type
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef char yes;
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef long no;
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static yes check( typename C::argument_type * );
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static no  check(...);
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic:
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    enum { value = sizeof(check<T>(0)) == sizeof(yes) };
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename T>
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass has_first_argument_type
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef char yes;
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef long no;
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static yes check( typename C::first_argument_type * );
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static no  check(...);
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic:
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    enum { value = sizeof(check<T>(0)) == sizeof(yes) };
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename T>
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass has_second_argument_type
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef char yes;
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    typedef long no;
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static yes check( typename C::second_argument_type *);
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    template <typename C> static no  check(...);
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic:
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    enum { value = sizeof(check<T>(0)) == sizeof(yes) };
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class F, class return_type>
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid test_nullary_function ()
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_argument_type<F>::value), "" );
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_first_argument_type<F>::value), "" );
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_second_argument_type<F>::value), "" );
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class F, class return_type, class arg_type>
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid test_unary_function ()
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::argument_type,  arg_type>::value), "" );
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_first_argument_type<F>::value), "" );
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_second_argument_type<F>::value), "" );
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class F, class return_type, class arg_type1, class arg_type2>
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid test_binary_function ()
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::result_type,        return_type>::value), "" );
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::first_argument_type,  arg_type1>::value), "" );
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::second_argument_type, arg_type2>::value), "" );
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_argument_type<F>::value), "" );
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class F, class return_type>
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid test_other_function ()
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_argument_type<F>::value), "" );
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_first_argument_type<F>::value), "" );
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static_assert((!has_second_argument_type<F>::value), "" );
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint main()
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test_nullary_function<std::function<int()>, int>();
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test_unary_function  <std::function<double(int)>, double, int>();
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test_binary_function <std::function<double(int, char)>, double, int, char>();
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test_other_function  <std::function<double(int, char, double)>, double>();
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
109