// bslstl_function_cpp03.h                                            -*-C++-*-

// Automatically generated file.  **DO NOT EDIT**

#ifndef INCLUDED_BSLSTL_FUNCTION_CPP03
#define INCLUDED_BSLSTL_FUNCTION_CPP03

//@PURPOSE: Provide C++03 implementation for bslstl_function.h
//
//@CLASSES: See bslstl_function.h for list of classes
//
//@SEE_ALSO: bslstl_function
//
//@DESCRIPTION:  This component is the C++03 translation of a C++11 component,
// generated by the 'sim_cpp11_features.pl' program.  If the original header
// contains any specially delimited regions of C++11 code, then this generated
// file contains the C++03 equivalent, i.e., with variadic templates expanded
// and rvalue-references replaced by 'bslmf::MovableRef' objects.  The header
// code in this file is designed to be '#include'd into the original header
// when compiling with a C++03 compiler.  If there are no specially delimited
// regions of C++11 code, then this header contains no code and is not
// '#include'd in the original header.
//
// Generated on Fri Aug 19 08:48:11 2022
// Command line: sim_cpp11_features.pl bslstl_function.h

#ifdef COMPILING_BSLSTL_FUNCTION_H

// 'BSLS_ASSERT' filename fix -- See {'bsls_assertimputil'}
#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
namespace BloombergLP {
extern const char s_bslstl_function_h[];
#undef BSLS_ASSERTIMPUTIL_FILE
#define BSLS_ASSERTIMPUTIL_FILE BloombergLP::s_bslstl_function_h
}  // close enterprise namespace
#endif

// FORWARD DECLARATIONS
namespace bsl {

template <class PROTOTYPE>
class function;
    // Forward declaration.

}  // close namespace bsl

namespace BloombergLP {

#ifndef BDE_OMIT_INTERNAL_DEPRECATED

template <class PROTOTYPE>
class bdef_Function;
    // Forward declaration of legacy 'bdef_Function' in order to implement
    // by-reference conversion from 'bsl::function<F>'.  This declaration
    // produces a by-name cyclic dependency between 'bsl' and 'bde' in order to
    // allow legacy code to transition to 'bsl::function' from (the deprecated)
    // 'bdef_Function'.  The conversion, and therefore this forward reference,
    // should not appear in the open-source version of this component.

#endif // BDE_OMIT_INTERNAL_DEPRECATED

namespace bslstl {

                        // =================================
                        // struct template Function_ArgTypes
                        // =================================

template <class PROTOTYPE>
struct Function_ArgTypes {
    // This component-private struct template provides the following nested
    // typedefs for 'bsl::function' for a specified 'PROTOTYPE' which must be a
    // function type:
    //..
    //  argument_type        -- Only if PROTOTYPE takes exactly one argument
    //  first_argument_type  -- Only if PROTOTYPE takes exactly two arguments
    //  second_argument_type -- Only if PROTOTYPE takes exactly two arguments
    //..
    // The C++ Standard requires that 'function' define these typedefs for
    // compatibility with one- and two-argument legacy (now deprecated) functor
    // adaptors.  'bsl::function' publicly inherits from an instantiation of
    // this template in order to conditionally declare the above nested types.
    // This primary (unspecialized) template provides no typedefs.
};

template <class RET, class ARG>
struct Function_ArgTypes<RET(ARG)> {
    // This component-private specialization of 'Function_ArgTypes' is for
    // function prototypes that take exactly one argument and provides an
    // 'argument_type' nested typedef.

    // PUBLIC TYPES
    BSLS_DEPRECATE_FEATURE("bsl",
                           "deprecated_cpp17_standard_library_features",
                           "do not use")
    typedef ARG argument_type;
        // !DEPRECATED!: This typedef is deprecated in C++17, for details see
        // https://isocpp.org/files/papers/p0005r4.html.
};

template <class RET, class ARG1, class ARG2>
struct Function_ArgTypes<RET(ARG1, ARG2)> {
    // This component-private specialization of 'Function_ArgTypes' is for
    // functions that take exactly two arguments and provides
    // 'first_argument_type' and 'second_argument_type' nested typedefs.

    // PUBLIC TYPES
    BSLS_DEPRECATE_FEATURE("bsl",
                           "deprecated_cpp17_standard_library_features",
                           "do not use")
    typedef ARG1 first_argument_type;
        // !DEPRECATED!: This typedef is deprecated in C++17, for details see
        // https://isocpp.org/files/papers/p0005r4.html.

    BSLS_DEPRECATE_FEATURE("bsl",
                           "deprecated_cpp17_standard_library_features",
                           "do not use")
    typedef ARG2 second_argument_type;
        // !DEPRECATED!: This typedef is deprecated in C++17, for details see
        // https://isocpp.org/files/papers/p0005r4.html.
};

                        // ================================
                        // class template Function_Variadic
                        // ================================

#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
// {{{ BEGIN GENERATED CODE
// Command line: sim_cpp11_features.pl bslstl_function.h
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT
#define BSLSTL_FUNCTION_VARIADIC_LIMIT 13
#endif
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT_A
#define BSLSTL_FUNCTION_VARIADIC_LIMIT_A BSLSTL_FUNCTION_VARIADIC_LIMIT
#endif

template <class PROTOTYPE>
class Function_Variadic;

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 0
template <class RET>
class Function_Variadic<RET()> : public Function_ArgTypes<RET()>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET()>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()() const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 0

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 1
template <class RET, class ARGS_01>
class Function_Variadic<RET(ARGS_01)> : public Function_ArgTypes<RET(ARGS_01)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 1

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 2
template <class RET, class ARGS_01,
                     class ARGS_02>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 2

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 3
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 3

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 4
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 4

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 5
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 5

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 6
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 6

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 7
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 7

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 8
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 8

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 9
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08,
                            ARGS_09)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08,
                                                                     ARGS_09)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type,
                        typename bslmf::ForwardingType<ARGS_09>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08,
                                   ARGS_09)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08,
                   ARGS_09 args_09) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 9

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 10
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08,
                            ARGS_09,
                            ARGS_10)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08,
                                                                     ARGS_09,
                                                                     ARGS_10)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type,
                        typename bslmf::ForwardingType<ARGS_09>::Type,
                        typename bslmf::ForwardingType<ARGS_10>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08,
                                   ARGS_09,
                                   ARGS_10)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08,
                   ARGS_09 args_09,
                   ARGS_10 args_10) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 10

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 11
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08,
                            ARGS_09,
                            ARGS_10,
                            ARGS_11)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08,
                                                                     ARGS_09,
                                                                     ARGS_10,
                                                                     ARGS_11)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type,
                        typename bslmf::ForwardingType<ARGS_09>::Type,
                        typename bslmf::ForwardingType<ARGS_10>::Type,
                        typename bslmf::ForwardingType<ARGS_11>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08,
                                   ARGS_09,
                                   ARGS_10,
                                   ARGS_11)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08,
                   ARGS_09 args_09,
                   ARGS_10 args_10,
                   ARGS_11 args_11) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 11

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 12
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08,
                            ARGS_09,
                            ARGS_10,
                            ARGS_11,
                            ARGS_12)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08,
                                                                     ARGS_09,
                                                                     ARGS_10,
                                                                     ARGS_11,
                                                                     ARGS_12)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type,
                        typename bslmf::ForwardingType<ARGS_09>::Type,
                        typename bslmf::ForwardingType<ARGS_10>::Type,
                        typename bslmf::ForwardingType<ARGS_11>::Type,
                        typename bslmf::ForwardingType<ARGS_12>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08,
                                   ARGS_09,
                                   ARGS_10,
                                   ARGS_11,
                                   ARGS_12)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08,
                   ARGS_09 args_09,
                   ARGS_10 args_10,
                   ARGS_11 args_11,
                   ARGS_12 args_12) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 12

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 13
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12,
                     class ARGS_13>
class Function_Variadic<RET(ARGS_01,
                            ARGS_02,
                            ARGS_03,
                            ARGS_04,
                            ARGS_05,
                            ARGS_06,
                            ARGS_07,
                            ARGS_08,
                            ARGS_09,
                            ARGS_10,
                            ARGS_11,
                            ARGS_12,
                            ARGS_13)> : public Function_ArgTypes<RET(ARGS_01,
                                                                     ARGS_02,
                                                                     ARGS_03,
                                                                     ARGS_04,
                                                                     ARGS_05,
                                                                     ARGS_06,
                                                                     ARGS_07,
                                                                     ARGS_08,
                                                                     ARGS_09,
                                                                     ARGS_10,
                                                                     ARGS_11,
                                                                     ARGS_12,
                                                                     ARGS_13)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS_01>::Type,
                        typename bslmf::ForwardingType<ARGS_02>::Type,
                        typename bslmf::ForwardingType<ARGS_03>::Type,
                        typename bslmf::ForwardingType<ARGS_04>::Type,
                        typename bslmf::ForwardingType<ARGS_05>::Type,
                        typename bslmf::ForwardingType<ARGS_06>::Type,
                        typename bslmf::ForwardingType<ARGS_07>::Type,
                        typename bslmf::ForwardingType<ARGS_08>::Type,
                        typename bslmf::ForwardingType<ARGS_09>::Type,
                        typename bslmf::ForwardingType<ARGS_10>::Type,
                        typename bslmf::ForwardingType<ARGS_11>::Type,
                        typename bslmf::ForwardingType<ARGS_12>::Type,
                        typename bslmf::ForwardingType<ARGS_13>::Type);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS_01,
                                   ARGS_02,
                                   ARGS_03,
                                   ARGS_04,
                                   ARGS_05,
                                   ARGS_06,
                                   ARGS_07,
                                   ARGS_08,
                                   ARGS_09,
                                   ARGS_10,
                                   ARGS_11,
                                   ARGS_12,
                                   ARGS_13)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS_01 args_01,
                   ARGS_02 args_02,
                   ARGS_03 args_03,
                   ARGS_04 args_04,
                   ARGS_05 args_05,
                   ARGS_06 args_06,
                   ARGS_07 args_07,
                   ARGS_08 args_08,
                   ARGS_09 args_09,
                   ARGS_10 args_10,
                   ARGS_11 args_11,
                   ARGS_12 args_12,
                   ARGS_13 args_13) const;
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_A >= 13

#else
// The generated code below is a workaround for the absence of perfect
// forwarding in some compilers.

template <class PROTOTYPE>
class Function_Variadic;

template <class RET, class... ARGS>
class Function_Variadic<RET(ARGS...)> : public Function_ArgTypes<RET(ARGS...)>
{

    typedef bslstl::Function_Rep Function_Rep;

    typedef RET Invoker(const Function_Rep *,
                        typename bslmf::ForwardingType<ARGS>::Type...);

  protected:
    Function_Rep d_rep;

  private:
    Function_Variadic(const Function_Variadic&) BSLS_KEYWORD_DELETED;
    Function_Variadic&
    operator=(const Function_Variadic&) BSLS_KEYWORD_DELETED;

    friend class bsl::function<RET(ARGS...)>;

  public:
    typedef RET                          result_type;
    typedef Function_Rep::allocator_type allocator_type;

    Function_Variadic(const allocator_type& allocator);


    RET operator()(ARGS... args) const;
};

// }}} END GENERATED CODE
#endif

              // =================================================
              // struct template Function_IsInvocableWithPrototype
              // =================================================

template <class PROTOTYPE, class FUNC>
struct Function_IsInvocableWithPrototype;
    // Forward declaration of the component-private
    // 'Function_IsInvocableWithPrototype' 'struct' template.  The primary
    // (unspecialized) template is not defined.  This 'struct' template
    // implements a boolean metafunction that publicly inherits from
    // 'bsl::true_type' if an object of the specified 'FUNC' type is invocable
    // under the specified 'PROTOTYPE', and inherits from 'bsl::false_type'
    // otherwise.  An object of 'FUNC' type is invocable under the 'PROTOTYPE'
    // if it is Lvalue-Callable with the arguments of the 'PROTOTYPE', and
    // returns an object of type convertible to the return type of the
    // 'PROTOTYPE'.  If the return type of the 'PROTOTYPE' is 'void', then any
    // type is considered convertible to the return type of the 'PROTOTYPE'.
    // In C++03, 'FUNC' is considered Lvalue-Callable with the argument and
    // return types of the 'PROTOTYPE' if it is not an integral type.  This
    // 'struct' template requires 'PROTOTYPE" to be an unqualified function
    // type.

}  // close package namespace
}  // close enterprise namespace

namespace bsl {

                    // =======================
                    // class template function
                    // =======================

template <class PROTOTYPE>
class function : public BloombergLP::bslstl::Function_Variadic<PROTOTYPE> {
    // This class template implements the C++ Standard Library 'std::function'
    // template, enhanced for allocator support as per Standards Proposal
    // P0987.  An instantiation of this template generalizes the notion of a
    // pointer to a function having the specified 'PROTOTYPE' expressed as a
    // function type (e.g., 'int(const char *, float)').  An object of this
    // class wraps a copy of the callable object specified at construction (if
    // any), such as a function pointer, member-function pointer, member-data
    // pointer, or functor object.  The wrapped object (called the *target* or
    // *target* *object*) is owned by the 'bsl::function' object (unlike the
    // function pointer that it mimics).  Invoking the 'bsl::function' object
    // will invoke the target (or throw an exception, if there is no target).
    // Note that 'function' will compile only if 'PROTOTYPE' is a function
    // type.
    //
    // To optimize away many heap allocations, objects of this type have a
    // buffer into which small callable objects can be stored.  In order to
    // qualify for this small-object optimization, a callable type must not
    // only fit in the buffer but must also be nothrow move constructible.  The
    // latter constraint allows this type to be nothrow move constructible and
    // nothrow swappable, as required by the C++ Standard.  The small object
    // buffer is guaranteed to be large enough to hold a pointer to function,
    // pointer to member function, pointer to member data, a
    // 'bsl::reference_wrapper', or an empty struct.  Although the standard
    // does not specify a minimum size beyond the aforementioned guarantee,
    // many small structs will fit in the small object buffer, as defined in
    // the 'bslstl_function_smallobjectoptimization' component.

  private:
    // PRIVATE TYPES
    typedef BloombergLP::bslstl::Function_Variadic<PROTOTYPE> Base;
    typedef BloombergLP::bslstl::Function_Rep                 Function_Rep;
    typedef BloombergLP::bslmf::MovableRefUtil                MovableRefUtil;

    template <class FROM, class TO>
    struct IsReferenceCompatible
    : BloombergLP::bslstl::Function_IsReferenceCompatible<FROM, TO>::type {
        // Abbreviation for metafunction that determines whether a reference
        // from 'FROM' can be cast to a reference to 'TO' without loss of
        // information.
    };

    template <class TYPE>
    struct Decay : MovableRefUtil::Decay<TYPE> {
        // Abbreviation for metafunction used to provide a C++03-compatible
        // implementation of 'std::decay' that treats 'bslmf::MovableReference'
        // as an rvalue reference.
    };

    template <class FUNC>
    struct IsInvocableWithPrototype
    : BloombergLP::bslstl::Function_IsInvocableWithPrototype<PROTOTYPE, FUNC> {
        // Abbreviation for a metafunction used to determine whether an object
        // of the specified 'FUNC' is callable with argument types of the
        // specified 'PROTOTYPE' and returns a type convertible to the return
        // type of the 'PROTOTYPE'.
    };

#ifndef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
    typedef BloombergLP::bsls::UnspecifiedBool<function> UnspecifiedBoolUtil;
    typedef typename UnspecifiedBoolUtil::BoolType       UnspecifiedBool;
        // Unique type that evaluates to true or false in a boolean control
        // construct such as an 'if' or 'while' statement.  In C++03,
        // 'function' is implicitly convertible to this type but is not
        // implicitly convertible to 'bool'.  In C++11 and later, 'function' is
        // explicitly convertible to 'bool', so this type is not needed.

    // NOT IMPLEMENTED
    bool operator==(const function&) const;  // Declared but not defined
    bool operator!=(const function&) const;  // Declared but not defined
        // Since 'function' does not support 'operator==' and 'operator!=',
        // they must be deliberately suppressed; otherwise 'function' objects
        // would be implicitly comparable by implicit conversion to
        // 'UnspecifiedBool'.
#endif // !defined(BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT)

    // PRIVATE MANIPULATORS
    template <class FUNC>
    void installFunc(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func);
        // Set the target of this 'function' by constructing from the specified
        // 'func' callable object.  If the type of 'func' is a movable
        // reference, then the target is constructed by extended move
        // construction; otherwise by extended copy construction.
        // Instantiation will fail unless 'FUNC' is a callable type that is
        // invocable with arguments in 'PROTOTYPE' and yields a return type
        // that is convertible to the return type in 'PROTOTYPE'.

  public:
    // TRAITS
    BSLMF_NESTED_TRAIT_DECLARATION(function,
                                   BloombergLP::bslma::UsesBslmaAllocator);
    BSLMF_NESTED_TRAIT_DECLARATION(function,
                                   BloombergLP::bslmf::UsesAllocatorArgT);
    BSLMF_NESTED_TRAIT_DECLARATION(function,
                                   bsl::is_nothrow_move_constructible);

    // TYPES
    typedef Function_Rep::allocator_type allocator_type;

    // CREATORS
    function() BSLS_KEYWORD_NOEXCEPT;
    function(nullptr_t) BSLS_KEYWORD_NOEXCEPT;                      // IMPLICIT
    function(allocator_arg_t       ,
             const allocator_type& allocator) BSLS_KEYWORD_NOEXCEPT;
    function(allocator_arg_t       ,
             const allocator_type& allocator,
             nullptr_t             ) BSLS_KEYWORD_NOEXCEPT;
        // Create an empty 'function' object.  Optionally specify an
        // 'allocator' (e.g., the address of a 'bslma::Allocator' object) to
        // supply memory; otherwise, the default allocator is used.

    template <class FUNC>
    function(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func,          // IMPLICIT
             typename enable_if<
                    ! IsReferenceCompatible<typename Decay<FUNC>::type,
                                            function>::value
                 &&   IsInvocableWithPrototype<
                                             typename Decay<FUNC>::type>::value
#ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
                 && ! MovableRefUtil::IsMovableReference<FUNC>::value
#endif
#ifdef BSLS_PLATFORM_CMP_IBM
                 && ! is_function<FUNC>::value
#endif
                 , int>::type = 0)
        // Create an object wrapping the specified 'func' callable object.  Use
        // the default allocator to supply memory.  If 'func' is a null pointer
        // or null pointer-to-member, then the resulting object will be empty.
        // This constructor will not participate in overload resolution if
        // 'func' is of the same type as (or reference compatible with) this
        // object (to avoid ambiguity with the copy and move constructors) or
        // is an integral type (to avoid matching null pointer literals).  In
        // C++03, this function will not participate in overload resolution if
        // 'FUNC' is a 'MovableRef' (see overload, below), and instantiation
        // will fail unless 'FUNC' is invocable using the arguments and return
        // type specified in 'PROTOTYPE'.  In C++11 and later, this function
        // will not participate in overload resolution if 'FUNC' is not
        // invocable using the arguments and return type specified in
        // 'PROTOTYPE'.  Note that this constructor implicitly converts from
        // any type that is so invocable.
        : Base(allocator_type())
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // The body of this constructor must be inlined inplace because the use
        // of 'enable_if' will otherwise break the MSVC 2010 compiler.
        //
        // The '! bsl::is_function<FUNC>::value' constraint is required in
        // C++03 mode when using the IBM XL C++ compiler.  In C++03,
        // 'BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func' expands to
        // 'const FUNC& func'.  A conforming compiler deduces a
        // reference-to-function type for 'func' when it binds to a function
        // argument.  The IBM XL C++ compiler erroneously does not collapse the
        // 'const' qualifier when 'FUNC' is deduced to be a function type, and
        // instead attempts to deduce the type of 'func' to be a reference to a
        // 'const'-qualified function.  This causes substitution to fail
        // because function-typed expressions are never 'const'.  This
        // component solves the problem by accepting a 'func' having a function
        // type as a pointer to a (non-'const') function.  An overload for the
        // corresponding constructor is defined below.

        installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
    }

#ifdef BSLS_PLATFORM_CMP_IBM
    template <class FUNC>
    function(FUNC                                            *func, // IMPLICIT
             typename enable_if<is_function<FUNC>::value, int>::type = 0)

        : Base(allocator_type())
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // This constructor overload only exists to work around an IBM XL C++
        // compiler defect.  See the implementation notes for the above
        // constructor overload for more information.
        //
        // This constructor also forwards the 'func' as a pointer-to-function
        // type to downstream operations in order to work around the
        // aforementioned reference-to-function type deduction defects.
        //
        // Further, note that instantiation of this constructor will fail
        // unless 'FUNC' is invocable using the arguments and return type
        // specified in 'PROTOTYPE'.  This component assumes that the IBM XL
        // C++ compiler does not support C++11 or later.

        installFunc(func);
    }
#endif

#ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
    template <class FUNC>
    explicit function(const BloombergLP::bslmf::MovableRef<FUNC>& func,
             typename enable_if<
                    ! IsReferenceCompatible<typename Decay<FUNC>::type,
                                            function>::value
                 &&   IsInvocableWithPrototype<
                                             typename Decay<FUNC>::type>::value
                 , int>::type = 0)
        // Create an object wrapping the specified 'func' callable object.
        // This constructor (ctor 2) is identical to the previous constructor
        // (ctor 1) except that, in C++03 ctor 2 provides for explicit
        // construction from a 'MovableRef' referencing a callable type, rather
        // than an implicit conversion for 'FUNC' not being a 'MovableRef'.  In
        // C++11, overload resolution matching an argument of type 'T&&' to a
        // parameter of type 'T' (exact match) is always preferred over
        // matching 'T&&' to 'bsl::function' (conversion).  In C++03, however
        // 'MovableRef' is not a real reference type, so it sometimes creates
        // overload ambiguities whereby matching 'MovableRef<T>' to 'T'
        // (conversion) is no better than matching 'MovableRef<T>' to
        // 'bsl::function' (also conversion).  This ambiguity is resolved by
        // making this constructor from 'MovableRef<T>' explicit, while leaving
        // other constructor from 'FUNC' implicit.  This means that
        // 'move' will fail in a narrow set of cases in C++03, as shown below:
        //..
        //  typedef bsl::function<void(int)> Obj;
        //  MyCallableType x;
        //
        //  Obj f1 = x;                              // OK
        //  Obj f2 = bslmf::MovableRefUtil::move(x); // No conversion in C++03
        //  Obj f3(bslmf::MovableRefUtil::move(x));  // OK, normal ctor call
        //
        //  void y(const Obj& f);
        //  y(x);                                    // OK
        //  y(bslmf::MovableRefUtil::move(x));       // Not found in C++03
        //  y(Obj(bslmf::MovableRefUtil::move(x)));  // OK, explicit cast
        //..
        // As you can see from the examples above, there are simple workarounds
        // for the problem cases, although generic code might need to be extra
        // careful.
        : Base(allocator_type())
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // The body of this constructor must inlined inplace because the use of
        // 'enable_if' will otherwise break the MSVC 2010 compiler.

        installFunc(BloombergLP::bslmf::MovableRefUtil::move(func));
    }
#endif

    template <class FUNC>
    function(allocator_arg_t,
             const allocator_type&                   allocator,
             BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func,
             typename enable_if<
                    ! IsReferenceCompatible<typename Decay<FUNC>::type,
                                            function>::value
                 &&   IsInvocableWithPrototype<
                                             typename Decay<FUNC>::type>::value
#ifdef BSLS_PLATFORM_CMP_IBM
                 && ! is_function<FUNC>::value
#endif
                 , int>::type = 0)
        // Create an object wrapping the specified 'func' callable object.  Use
        // the specified 'allocator' (i.e., the address of a 'bslma::Allocator'
        // object) to supply memory.  If 'func' is a null pointer or null
        // pointer-to-member, then the resulting object will be empty.  This
        // constructor will not participate in overload resolution if 'func' is
        // of the same type as (or reference compatible with) this object (to
        // avoid ambiguity with the extended copy and move constructors) or is
        // an integral type (to avoid matching null pointer literals).  In
        // C++03, this function will not participate in overload resolution if
        // 'FUNC' is a 'MovableRef' (see overload, below), and instantiation
        // will fail unless 'FUNC' is invocable using the arguments and return
        // type specified in 'PROTOTYPE'.  In C++11 and later, this function
        // will not participate in overload resolution if 'FUNC' is not
        // invocable using the arguments and return type specified in
        // 'PROTOTYPE'.  Note that this constructor implicitly converts from
        // any type that is so invocable.
        : Base(allocator)
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // The body of this constructor must inlined inplace because the use of
        // 'enable_if' will otherwise break the MSVC 2010 compiler.
        //
        // The '! bsl::is_function<FUNC>::value' constraint is required in
        // C++03 mode when using the IBM XL C++ compiler.  In C++03,
        // 'BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func' expands to
        // 'const FUNC& func'.  A conforming compiler deduces a
        // reference-to-function type for 'func' when it binds to a function
        // argument.  The IBM XL C++ compiler erroneously does not collapse the
        // 'const' qualifier when 'FUNC' is deduced to be a function type, and
        // instead attempts to deduce the type of 'func' to be a reference to a
        // 'const'-qualified function.  This causes substitution to fail
        // because function-typed expressions are never 'const'.  This
        // component solves the problem by accepting a 'func' having a function
        // type as a pointer to a (non-'const') function.  An overload for the
        // corresponding constructor is defined below.

        installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
    }

#ifdef BSLS_PLATFORM_CMP_IBM
    template <class FUNC>
    function(allocator_arg_t,
             const allocator_type&                                   allocator,
             FUNC                                                   *func,
             typename enable_if<is_function<FUNC>::value, int>::type = 0)
        : Base(allocator)
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // This constructor overload only exists to work around an IBM XL C++
        // compiler defect.  See the implementation notes for the above
        // constructor overload for more information.
        //
        // This constructor also forwards the 'func' as a pointer-to-function
        // type to downstream operations in order to work around the
        // aforementioned reference-to-function type deduction defects.
        //
        // Further, note that instantiation of this constructor will fail
        // unless 'FUNC' is invocable using the arguments and return type
        // specified in 'PROTOTYPE'.  This component assumes that the IBM XL
        // C++ compiler does not support C++11 or later.

        installFunc(func);
    }
#endif

    function(const function&       original);
    function(allocator_arg_t       ,
             const allocator_type& allocator,
             const function&       original);
        // Create a 'function' having the same value as (i.e., wrapping a copy
        // of the target held by) the specified 'original' object.  Optionally
        // specify an 'allocator' (e.g., the address of a 'bslma::Allocator'
        // object) to supply memory; otherwise, the default allocator is used.

    function(BloombergLP::bslmf::MovableRef<function> original)
                                             BSLS_KEYWORD_NOEXCEPT; // IMPLICIT
        // Create a 'function' having the same target as the specified
        // 'original' object.  Use 'original.get_allocator()' as the allocator
        // to supply memory.  The 'original' object is set to empty after the
        // new object is created.  If the target qualifies for the small-object
        // optimization (see class-level documentation), then it is
        // move-constructed into the new object; otherwise ownership of the
        // target is transferred without using the target's move constructor.

    function(allocator_arg_t                          ,
             const allocator_type&                    allocator,
             BloombergLP::bslmf::MovableRef<function> original);
        // Create a 'function' having the same value as (i.e., wrapping a copy
        // of the target held by) the specified 'original' object.  Use the
        // specified 'allocator' (e.g., the address of a 'bslma::Allocator'
        // object) to supply memory.  If 'allocator == original.allocator()',
        // this object is created as if by move construction; otherwise it is
        // created as if by extended copy construction using 'allocator'.

    // MANIPULATORS
    function& operator=(const function& rhs);
        // Set the target of this object to a copy of the target (if any)
        // held by the specified 'rhs' object, destroy the target (if any)
        // previously held by '*this', and return '*this'.  The result is
        // equivalent to having constructed '*this' from 'rhs' using the
        // extended copy constructor with allocator 'this->get_allocator()'.
        // If an exception is thrown, '*this' is not modified (i.e., copy
        // assignment provides the strong exception guarantee).

    function& operator=(BloombergLP::bslmf::MovableRef<function> rhs);
        // Set the target of this object to the target (if any) held by the
        // specified 'rhs' object, destroy the target (if any) previously held
        // by '*this', and return '*this'.  The result is equivalent to having
        // constructed '*this' from 'rhs' using the extended move constructor
        // with allocator 'this->get_allocator()'.  If an exception is thrown,
        // 'rhs' will have a valid but unspecified value and '*this' will not
        // be modified.  Note that an exception will never be thrown if
        // 'get_allocator() == rhs.get_allocator()'.

    template <class FUNC>
    typename enable_if<
           ! IsReferenceCompatible<typename Decay<FUNC>::type, function>::value
        &&   IsInvocableWithPrototype<typename Decay<FUNC>::type>::value
     , function&>::type
    operator=(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) rhs)
        // Set the target of this object to the specified 'rhs' callable
        // object, destroy the previous target (if any), and return '*this'.
        // The result is equivalent to having constructed '*this' from
        // 'std::forward<FUNC>(rhs)' and 'this->get_allocator()'.  Note that
        // this assignment operator will not participate in overload resolution
        // if 'func' is of the same type as this object (to avoid ambiguity
        // with the copy and move assignment operators.)  In C++03,
        // instantiation will fail unless 'FUNC' is invocable with the
        // arguments and return type specified in 'PROTOTYPE'.  In C++11 and
        // later, this assignment operator will not participate in overload
        // resolution unless 'FUNC' is invocable with the arguments and return
        // type specified in 'PROTOTYPE'.
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // The body of this operator must inlined inplace because the use of
        // 'enable_if' will otherwise break the MSVC 2010 compiler.

        function(allocator_arg, this->get_allocator(),
                 BSLS_COMPILERFEATURES_FORWARD(FUNC, rhs)).swap(*this);
        return *this;
    }

#ifdef BSLS_PLATFORM_CMP_IBM
    template <class FUNC>
    typename enable_if<is_function<FUNC>::value, function&>::type
    operator=(FUNC *rhs)
        // Set the target of this object to the specified 'rhs' function
        // pointer.  This overload exists only for the IBM compiler, which has
        // trouble decaying functions to function pointers in
        // pass-by-const-reference template arguments.
    {
        ///Implementation Note
        ///- - - - - - - - - -
        // The body of this operator must inlined inplace.
        //
        // Further, note that instantiation of this assignment operator will
        // fail unless 'FUNC' is invocable using the arguments and return type
        // specified in 'PROTOTYPE'.  This component assumes that the IBM XL
        // C++ compiler does not support C++11 or later.

        function(allocator_arg, this->get_allocator(), rhs).swap(*this);
        return *this;
    }
#endif

    template <class FUNC>
    typename enable_if<
             IsInvocableWithPrototype<typename Decay<FUNC>::type>::value
     , function &>::type
    operator=(bsl::reference_wrapper<FUNC> rhs) BSLS_KEYWORD_NOEXCEPT
        // Destroy the current target (if any) of this object, then set the
        // target to the specified 'rhs' wrapper containing a reference to a
        // callable object and return '*this'.  The result is equivalent to
        // having constructed '*this' from 'rhs' and 'this->get_allocator()'.
        // Note that this assignment is a separate overload only because it is
        // unconditionally 'noexcept'.
    {
        /// Implementation Note
        ///- - - - - - - - - -
        // The body of this operator must inlined inplace because the use of
        // 'enable_if' will otherwise break the MSVC 2010 compiler.

        function(allocator_arg, this->get_allocator(), rhs).swap(*this);
        return *this;
    }

    function& operator=(nullptr_t) BSLS_KEYWORD_NOEXCEPT;
        // Set this object to empty and return '*this'.

    // Inherit 'operator()' from 'Function_Variadic' base class.
    using Base::operator();
        // If this object is empty, throw 'bsl::bad_function_call'; otherwise
        // invoke the target object with the specified 'args...' and return the
        // result (after conversion to 'RET').  Note that, even though it is
        // declared 'const', this call operator can mutate the target object
        // and is thus considered a manipulator rather than an accessor.

    void swap(function& other) BSLS_KEYWORD_NOEXCEPT;
        // Exchange the targets held by this 'function' and the specified
        // 'other' 'function'.  The behavior is undefined unless
        // 'get_allocator() == other.get_allocator()'.

    template<class TP> TP* target() BSLS_KEYWORD_NOEXCEPT;
        // If 'TP' is the same type as the target object, returns a pointer
        // granting modifiable access to the target; otherwise return a null
        // pointer.

    // ACCESSORS
#ifdef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
    explicit  // Explicit conversion available only with C++11
    operator bool() const BSLS_KEYWORD_NOEXCEPT;
        // (C++11 and later) Return false if this object is empty, otherwise
        // return true.  Note that this is an explicit conversion operator and
        // is typically invoked implicitly in contexts such as in the condition
        // of an 'if' or 'while' statement, though it can also be invoked via
        // an explicit cast.
#else
    operator UnspecifiedBool() const BSLS_KEYWORD_NOEXCEPT
        // (C++03 only) Return a null value if this object is empty, otherwise
        // an arbitrary non-null value.  Note that this operator will be
        // invoked implicitly in boolean contexts such as in the condition of
        // an 'if' or 'while' statement, but does not constitute an implicit
        // conversion to 'bool'.
    {
        // Inplace inlined to work around xlC bug when out-of-line.
        return UnspecifiedBoolUtil::makeValue(0 != this->d_rep.invoker());
    }
#endif

    allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT;
        // Return (a copy of) the allocator used to supply memory for this
        // 'function'.

    template<class TP> const TP* target() const BSLS_KEYWORD_NOEXCEPT;
        // If 'TP' is the same type as the target object, returns a pointer
        // granting read-only access to the target; otherwise return a null
        // pointer.

    const std::type_info& target_type() const BSLS_KEYWORD_NOEXCEPT;
        // Return 'typeid(void)' if this object is empty; otherwise
        // 'typeid(FUNC)' where 'FUNC' is the type of the target object.

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
    // LEGACY METHODS
    operator BloombergLP::bdef_Function<PROTOTYPE *>&() BSLS_KEYWORD_NOEXCEPT;
        // !DEPRECATED!: Use 'bsl::function' instead of 'bdef_Function'.
        //
        // Return '*this', converted to a mutable 'bdef_Function' reference by
        // downcasting.  The behavior is undefined unless 'bdef_Function<F*>'
        // is derived from 'bsl::function<F>' and adds no new data members.

    operator const BloombergLP::bdef_Function<PROTOTYPE *>&() const
                                                         BSLS_KEYWORD_NOEXCEPT;
        // !DEPRECATED!: Use 'bsl::function' instead of 'bdef_Function'.
        //
        // Return '*this' converted to a const 'bdef_Function' reference by
        // downcasting.  The behavior is undefined unless 'bdef_Function<F*>'
        // is derived from 'bsl::function<F>' and adds no new data members.

    // LEGACY ACCESSORS
    BloombergLP::bslma::Allocator *allocator() const BSLS_KEYWORD_NOEXCEPT;
        // !DEPRECATED!: Use 'get_allocator()' instead.
        //
        // Return 'get_allocator().mechanism()'.  Note that this function
        // exists for BDE compatibility and is not part of the C++ Standard
        // Library.

    bool isInplace() const BSLS_KEYWORD_NOEXCEPT;
        // !DEPRECATED!: Runtime checking of this optimization is discouraged.
        //
        // Return 'true' if this 'function' is empty or if it is non-empty and
        // its target qualifies for the small-object optimization (and is thus
        // allocated within this object's footprint); otherwise, return false.
#endif
};

#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
// CLASS TEMPLATE DEDUCTION GUIDES

template<class RET, class... ARGS>
function(RET(*)(ARGS...)) -> function<RET(ARGS...)>;
    // Deduce the template parameter 'PROTOTYPE' from the signature of the
    // function supplied to the constructor of 'function'.

template<class ALLOC, class RET, class... ARGS>
function(allocator_arg_t, ALLOC, RET(*)(ARGS...)) -> function<RET(ARGS...)>;
    // Deduce the template parameter 'PROTOTYPE' from the signature of the
    // function supplied to the constructor of 'function'.


struct FunctionDeductionHelper {
    // This struct provides a set of template 'meta-functions' that extract
    // the signature of a class member function, stripping any qualifiers such
    // as 'const', 'noexcept' or '&'.

  public:
    // PUBLIC TYPES
    template<class FUNCTOR>
    struct StripSignature {};

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...)>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) const>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) noexcept>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) const noexcept>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) &>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) const &>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) & noexcept>
        { using Sig = RET(ARGS...); };

    template<class RET, class FUNCTOR, class ...ARGS>
    struct StripSignature<RET (FUNCTOR::*) (ARGS...) const & noexcept>
        { using Sig = RET(ARGS...); };
};

template <
    class FP,
    class PROTOTYPE = typename
        FunctionDeductionHelper::StripSignature<decltype(&FP::operator())>::Sig
    >
function(FP) -> function<PROTOTYPE>;
    // Deduce the template parameter 'PROTOTYPE' from the signature of the
    // 'operator()' of the functor supplied to the constructor of 'function'.

template <
    class ALLOC,
    class FP,
    class PROTOTYPE = typename
        FunctionDeductionHelper::StripSignature<decltype(&FP::operator())>::Sig
    >
function(allocator_arg_t, ALLOC, FP) -> function<PROTOTYPE>;
    // Deduce the template parameter 'PROTOTYPE' from the signature of the
    // 'operator()' of the functor supplied to the constructor of 'function'.
#endif

// FREE FUNCTIONS
template <class PROTOTYPE>
bool operator==(const function<PROTOTYPE>&, nullptr_t) BSLS_KEYWORD_NOEXCEPT;
template <class PROTOTYPE>
bool operator==(nullptr_t, const function<PROTOTYPE>&) BSLS_KEYWORD_NOEXCEPT;
    // Return true if the 'function' argument is empty, otherwise return false.

template <class PROTOTYPE>
bool operator!=(const function<PROTOTYPE>&, nullptr_t) BSLS_KEYWORD_NOEXCEPT;
template <class PROTOTYPE>
bool operator!=(nullptr_t, const function<PROTOTYPE>&) BSLS_KEYWORD_NOEXCEPT;
    // Return false if the 'function' argument is empty, otherwise return true.

template <class PROTOTYPE>
void swap(function<PROTOTYPE>& a,function<PROTOTYPE>& b) BSLS_KEYWORD_NOEXCEPT;
    // Exchange the targets held by the specified 'a' and specified 'b'
    // objects.  The behavior is undefined unless 'a.get_allocator() ==
    // b.get_allocator()'.

}  // close namespace bsl

// ============================================================================
//                     TEMPLATE AND INLINE FUNCTION DEFINITIONS
// ============================================================================

namespace BloombergLP {

#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
// {{{ BEGIN GENERATED CODE
// Command line: sim_cpp11_features.pl bslstl_function.h
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT
#define BSLSTL_FUNCTION_VARIADIC_LIMIT 13
#endif
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT_B
#define BSLSTL_FUNCTION_VARIADIC_LIMIT_B BSLSTL_FUNCTION_VARIADIC_LIMIT
#endif


#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 0
template <class RET>
inline
bslstl::Function_Variadic<RET()>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 0

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 1
template <class RET, class ARGS_01>
inline
bslstl::Function_Variadic<RET(ARGS_01)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 1

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 2
template <class RET, class ARGS_01,
                     class ARGS_02>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 2

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 3
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 3

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 4
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 4

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 5
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 5

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 6
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 6

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 7
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 7

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 8
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 8

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 9
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08,
                              ARGS_09)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 9

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 10
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08,
                              ARGS_09,
                              ARGS_10)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 10

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 11
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08,
                              ARGS_09,
                              ARGS_10,
                              ARGS_11)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 11

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 12
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08,
                              ARGS_09,
                              ARGS_10,
                              ARGS_11,
                              ARGS_12)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 12

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 13
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12,
                     class ARGS_13>
inline
bslstl::Function_Variadic<RET(ARGS_01,
                              ARGS_02,
                              ARGS_03,
                              ARGS_04,
                              ARGS_05,
                              ARGS_06,
                              ARGS_07,
                              ARGS_08,
                              ARGS_09,
                              ARGS_10,
                              ARGS_11,
                              ARGS_12,
                              ARGS_13)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 13


#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 0
template <class RET>
inline
RET bslstl::Function_Variadic<RET()>::operator()() const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 0

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 1
template <class RET, class ARGS_01>
inline
RET bslstl::Function_Variadic<RET(ARGS_01)>::operator()(ARGS_01 args_01) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 1

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 2
template <class RET, class ARGS_01,
                     class ARGS_02>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 2

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 3
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 3

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 4
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 4

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 5
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 5

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 6
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 6

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 7
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 7

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 8
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 8

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 9
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08,
                                  ARGS_09)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08,
                                                        ARGS_09 args_09) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08,
                             args_09);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 9

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 10
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08,
                                  ARGS_09,
                                  ARGS_10)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08,
                                                        ARGS_09 args_09,
                                                        ARGS_10 args_10) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08,
                             args_09,
                             args_10);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 10

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 11
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08,
                                  ARGS_09,
                                  ARGS_10,
                                  ARGS_11)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08,
                                                        ARGS_09 args_09,
                                                        ARGS_10 args_10,
                                                        ARGS_11 args_11) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08,
                             args_09,
                             args_10,
                             args_11);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 11

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 12
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08,
                                  ARGS_09,
                                  ARGS_10,
                                  ARGS_11,
                                  ARGS_12)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08,
                                                        ARGS_09 args_09,
                                                        ARGS_10 args_10,
                                                        ARGS_11 args_11,
                                                        ARGS_12 args_12) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08,
                             args_09,
                             args_10,
                             args_11,
                             args_12);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 12

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 13
template <class RET, class ARGS_01,
                     class ARGS_02,
                     class ARGS_03,
                     class ARGS_04,
                     class ARGS_05,
                     class ARGS_06,
                     class ARGS_07,
                     class ARGS_08,
                     class ARGS_09,
                     class ARGS_10,
                     class ARGS_11,
                     class ARGS_12,
                     class ARGS_13>
inline
RET bslstl::Function_Variadic<RET(ARGS_01,
                                  ARGS_02,
                                  ARGS_03,
                                  ARGS_04,
                                  ARGS_05,
                                  ARGS_06,
                                  ARGS_07,
                                  ARGS_08,
                                  ARGS_09,
                                  ARGS_10,
                                  ARGS_11,
                                  ARGS_12,
                                  ARGS_13)>::operator()(ARGS_01 args_01,
                                                        ARGS_02 args_02,
                                                        ARGS_03 args_03,
                                                        ARGS_04 args_04,
                                                        ARGS_05 args_05,
                                                        ARGS_06 args_06,
                                                        ARGS_07 args_07,
                                                        ARGS_08 args_08,
                                                        ARGS_09 args_09,
                                                        ARGS_10 args_10,
                                                        ARGS_11 args_11,
                                                        ARGS_12 args_12,
                                                        ARGS_13 args_13) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args_01,
                             args_02,
                             args_03,
                             args_04,
                             args_05,
                             args_06,
                             args_07,
                             args_08,
                             args_09,
                             args_10,
                             args_11,
                             args_12,
                             args_13);
}
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_B >= 13

#else
// The generated code below is a workaround for the absence of perfect
// forwarding in some compilers.


template <class RET, class... ARGS>
inline
bslstl::Function_Variadic<RET(ARGS...)>::
Function_Variadic(const allocator_type& allocator)
    : d_rep(allocator)
{
}

template <class RET, class... ARGS>
inline
RET bslstl::Function_Variadic<RET(ARGS...)>::operator()(ARGS... args) const
{
    Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());

#ifdef BDE_BUILD_TARGET_EXC
    if (! invoker_p) {
        throw bsl::bad_function_call();
    }
#else
    BSLS_ASSERT_OPT(invoker_p);
#endif

    return invoker_p(&d_rep, args...);
}

// }}} END GENERATED CODE
#endif

namespace bslstl {

#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
// {{{ BEGIN GENERATED CODE
// Command line: sim_cpp11_features.pl bslstl_function.h
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT
#define BSLSTL_FUNCTION_VARIADIC_LIMIT 13
#endif
#ifndef BSLSTL_FUNCTION_VARIADIC_LIMIT_C
#define BSLSTL_FUNCTION_VARIADIC_LIMIT_C BSLSTL_FUNCTION_VARIADIC_LIMIT
#endif


#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 0
template <class RET, class FUNC>
struct Function_IsInvocableWithPrototype<RET(), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 0

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 1
template <class RET, class FUNC, class ARGS_01>
struct Function_IsInvocableWithPrototype<RET(ARGS_01), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 1

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 2
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 2

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 3
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 3

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 4
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 4

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 5
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 5

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 6
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 6

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 7
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 7

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 8
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 8

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 9
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08,
                                            ARGS_09), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 9

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 10
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08,
                                            ARGS_09,
                                            ARGS_10), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 10

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 11
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08,
                                            ARGS_09,
                                            ARGS_10,
                                            ARGS_11), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 11

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 12
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11,
                                 class ARGS_12>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11,
                                             ARGS_12), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08,
                                            ARGS_09,
                                            ARGS_10,
                                            ARGS_11,
                                            ARGS_12), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 12

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 13
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11,
                                 class ARGS_12,
                                 class ARGS_13>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11,
                                             ARGS_12,
                                             ARGS_13), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS_01,
                                            ARGS_02,
                                            ARGS_03,
                                            ARGS_04,
                                            ARGS_05,
                                            ARGS_06,
                                            ARGS_07,
                                            ARGS_08,
                                            ARGS_09,
                                            ARGS_10,
                                            ARGS_11,
                                            ARGS_12,
                                            ARGS_13), FUNC> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 13


#else

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 0
template <class RET, class FUNC>
struct Function_IsInvocableWithPrototype<RET(), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 0

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 1
template <class RET, class FUNC, class ARGS_01>
struct Function_IsInvocableWithPrototype<RET(ARGS_01), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 1

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 2
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 2

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 3
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 3

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 4
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 4

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 5
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 5

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 6
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 6

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 7
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 7

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 8
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 8

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 9
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 9

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 10
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 10

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 11
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 11

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 12
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11,
                                 class ARGS_12>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11,
                                             ARGS_12), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 12

#if BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 13
template <class RET, class FUNC, class ARGS_01,
                                 class ARGS_02,
                                 class ARGS_03,
                                 class ARGS_04,
                                 class ARGS_05,
                                 class ARGS_06,
                                 class ARGS_07,
                                 class ARGS_08,
                                 class ARGS_09,
                                 class ARGS_10,
                                 class ARGS_11,
                                 class ARGS_12,
                                 class ARGS_13>
struct Function_IsInvocableWithPrototype<RET(ARGS_01,
                                             ARGS_02,
                                             ARGS_03,
                                             ARGS_04,
                                             ARGS_05,
                                             ARGS_06,
                                             ARGS_07,
                                             ARGS_08,
                                             ARGS_09,
                                             ARGS_10,
                                             ARGS_11,
                                             ARGS_12,
                                             ARGS_13), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};
#endif  // BSLSTL_FUNCTION_VARIADIC_LIMIT_C >= 13


#endif
#else
// The generated code below is a workaround for the absence of perfect
// forwarding in some compilers.


#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE

template <class RET, class FUNC, class... ARGS>
struct Function_IsInvocableWithPrototype<RET(ARGS...), FUNC>
: Function_InvokerUtil::IsFuncInvocable<RET(ARGS...), FUNC> {
};

#else

template <class RET, class FUNC, class... ARGS>
struct Function_IsInvocableWithPrototype<RET(ARGS...), FUNC>
: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
};

#endif
// }}} END GENERATED CODE
#endif

}  // close package namespace
}  // close enterprise namespace

                        // ----------------------------
                        // class template bsl::function
                        // ----------------------------

// PRIVATE MANIPULATORS
template <class PROTOTYPE>
template <class FUNC>
inline
void bsl::function<PROTOTYPE>::installFunc(
                                  BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func)
{
    typedef BloombergLP::bslstl::Function_InvokerUtil InvokerUtil;
    typedef InvokerUtil::GenericInvoker               GenericInvoker;
    typedef typename Decay<FUNC>::type                DecayedFunc;

    const DecayedFunc& decayedFunc = func;  // Force function-to-pointer decay.
    GenericInvoker *const invoker =
        InvokerUtil::invokerForFunc<PROTOTYPE>(decayedFunc);

    this->d_rep.installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func),
                            invoker);
}

// CREATORS
template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>::function() BSLS_KEYWORD_NOEXCEPT
    : Base(allocator_type())
{
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>::function(nullptr_t) BSLS_KEYWORD_NOEXCEPT
    : Base(allocator_type())
{
}

template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::function(allocator_arg_t       ,
                                   const allocator_type& allocator)
                                                          BSLS_KEYWORD_NOEXCEPT
    : Base(allocator)
{
}

template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::function(allocator_arg_t       ,
                                   const allocator_type& allocator,
                                   nullptr_t) BSLS_KEYWORD_NOEXCEPT
    : Base(allocator)
{
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>::function(const function& original)
    : Base(allocator_type())
{
    this->d_rep.copyInit(original.d_rep);
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>::function(allocator_arg_t,
                                          const allocator_type& allocator,
                                          const function&       original)
    : Base(allocator)
{
    this->d_rep.copyInit(original.d_rep);
}

template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::function(
       BloombergLP::bslmf::MovableRef<function> original) BSLS_KEYWORD_NOEXCEPT
    : Base(MovableRefUtil::access(original).get_allocator())
{
    this->d_rep.moveInit(&MovableRefUtil::access(original).d_rep);
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>::function(
                            allocator_arg_t,
                            const allocator_type&                    allocator,
                            BloombergLP::bslmf::MovableRef<function> original)
    : Base(allocator)
{
    this->d_rep.moveInit(&MovableRefUtil::access(original).d_rep);
}

// MANIPULATORS
template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>&
bsl::function<PROTOTYPE>::operator=(const function& rhs)
{
    function temp(allocator_arg, this->get_allocator(), rhs);
    this->d_rep.makeEmpty();            // Won't throw
    this->d_rep.moveInit(&temp.d_rep);  // Won't throw
    return *this;
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>&
bsl::function<PROTOTYPE>::operator=(
                                  BloombergLP::bslmf::MovableRef<function> rhs)
{
    function temp(allocator_arg, this->get_allocator(),
                  MovableRefUtil::move(rhs));
    this->d_rep.makeEmpty();            // Won't throw
    this->d_rep.moveInit(&temp.d_rep);  // Won't throw
    return *this;
}

template <class PROTOTYPE>
inline bsl::function<PROTOTYPE>&
bsl::function<PROTOTYPE>::operator=(nullptr_t) BSLS_KEYWORD_NOEXCEPT
{
    this->d_rep.makeEmpty();
    return *this;
}

template <class PROTOTYPE>
inline
void bsl::function<PROTOTYPE>::swap(function& other) BSLS_KEYWORD_NOEXCEPT
{
    this->d_rep.swap(other.d_rep);  // Won't throw
}

template <class PROTOTYPE>
template<class TP>
inline
TP *bsl::function<PROTOTYPE>::target() BSLS_KEYWORD_NOEXCEPT
{
    return this->d_rep.template target<TP>();
}

// ACCESSORS

#ifdef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::operator bool() const BSLS_KEYWORD_NOEXCEPT
{
    // If there is an invoker, then this function is non-empty (return true);
    // otherwise it is empty (return false).
    return 0 != this->d_rep.invoker();
}
#endif // BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT

template <class PROTOTYPE>
inline
typename bsl::function<PROTOTYPE>::allocator_type
bsl::function<PROTOTYPE>::get_allocator() const BSLS_KEYWORD_NOEXCEPT
{
    return this->d_rep.get_allocator();
}

template <class PROTOTYPE>
template<class TP>
inline
const TP* bsl::function<PROTOTYPE>::target() const BSLS_KEYWORD_NOEXCEPT
{
#if defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION < 1900
    // MSVC 2013 has a problem with implicit conversion to 'const nullptr_t*'.
    return (const TP*) this->d_rep.target<TP>();
#else
    return this->d_rep.template target<TP>();
#endif
}

template <class PROTOTYPE>
const std::type_info&
bsl::function<PROTOTYPE>::target_type() const BSLS_KEYWORD_NOEXCEPT
{
    return this->d_rep.target_type();
}

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
// CONVERSIONS TO LEGACY TYPE
template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::operator BloombergLP::bdef_Function<PROTOTYPE *>&()
                                                          BSLS_KEYWORD_NOEXCEPT
{
    typedef BloombergLP::bdef_Function<PROTOTYPE *> Ret;
    return *static_cast<Ret*>(this);
}

template <class PROTOTYPE>
inline
bsl::function<PROTOTYPE>::
operator const BloombergLP::bdef_Function<PROTOTYPE *>&() const
                                                          BSLS_KEYWORD_NOEXCEPT
{
    typedef const BloombergLP::bdef_Function<PROTOTYPE *> Ret;
    return *static_cast<Ret*>(this);
}

template <class PROTOTYPE>
inline
BloombergLP::bslma::Allocator *
bsl::function<PROTOTYPE>::allocator() const BSLS_KEYWORD_NOEXCEPT
{
    return get_allocator().mechanism();
}

template <class PROTOTYPE>
inline
bool bsl::function<PROTOTYPE>::isInplace() const BSLS_KEYWORD_NOEXCEPT
{
    return this->d_rep.isInplace();
}
#endif // BDE_OMIT_INTERNAL_DEPRECATED

// FREE FUNCTIONS
template <class PROTOTYPE>
inline
bool bsl::operator==(const bsl::function<PROTOTYPE>& f,
                     bsl::nullptr_t) BSLS_KEYWORD_NOEXCEPT
{
    return !f;
}

template <class PROTOTYPE>
inline
bool bsl::operator==(bsl::nullptr_t,
                     const bsl::function<PROTOTYPE>& f) BSLS_KEYWORD_NOEXCEPT
{
    return !f;
}

template <class PROTOTYPE>
inline
bool bsl::operator!=(const bsl::function<PROTOTYPE>& f,
                     bsl::nullptr_t                   ) BSLS_KEYWORD_NOEXCEPT
{
    return !!f;
}

template <class PROTOTYPE>
inline
bool bsl::operator!=(bsl::nullptr_t,
                     const bsl::function<PROTOTYPE>& f) BSLS_KEYWORD_NOEXCEPT
{
    return !!f;
}

template <class PROTOTYPE>
inline
void bsl::swap(bsl::function<PROTOTYPE>& a,
               bsl::function<PROTOTYPE>& b) BSLS_KEYWORD_NOEXCEPT
{
    a.swap(b);
}

       // --------------------------------------------------------------
       // specialization of class template Function_InvokerUtil_Dispatch
       // --------------------------------------------------------------

namespace BloombergLP {
namespace bslstl {

template <class PROTO>
struct Function_InvokerUtilNullCheck<bsl::function<PROTO> > {
    // Specialization of null checker for instantiations of 'bsl::function'.
    // This specialization treats an empty 'bsl::function' as a null object.

    // CLASS METHODS
    static bool isNull(const bsl::function<PROTO>& f)
        // Return true if the 'bsl::function' specified by 'f' is empty; else
        // false.
    {
        return !f;
    }
};

}  //  close package namespace
}  //  close enterprise namespace

// Undo 'BSLS_ASSERT' filename fix -- See {'bsls_assertimputil'}
#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
#undef BSLS_ASSERTIMPUTIL_FILE
#define BSLS_ASSERTIMPUTIL_FILE BSLS_ASSERTIMPUTIL_DEFAULTFILE
#endif

#else // if ! defined(DEFINED_BSLSTL_FUNCTION_H)
# error Not valid except when included from bslstl_function.h
#endif // ! defined(COMPILING_BSLSTL_FUNCTION_H)

#endif // ! defined(INCLUDED_BSLSTL_FUNCTION_CPP03)

// ----------------------------------------------------------------------------
// Copyright 2022 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------