namespace std {
  template<class> class function; // not defined
  template<class R, class... ArgTypes>
  class function<R(ArgTypes...)> {
  public:
    using result_type = R;
    // [func.wrap.func.con], construct/copy/destroy
    function() noexcept;
    function(nullptr_t) noexcept;
    function(const function&);
    function(function&&);
    template<class F> function(F);
    function& operator=(const function&);
    function& operator=(function&&);
    function& operator=(nullptr_t) noexcept;
    template<class F> function& operator=(F&&);
    template<class F> function& operator=(reference_wrapper<F>) noexcept;
    ~function();
    // [func.wrap.func.mod], function modifiers
    void swap(function&) noexcept;
    // [func.wrap.func.cap], function capacity
    explicit operator bool() const noexcept;
    // [func.wrap.func.inv], function invocation
    R operator()(ArgTypes...) const;
    // [func.wrap.func.targ], function target access
    const type_info& target_type() const noexcept;
    template<class T>       T* target() noexcept;
    template<class T> const T* target() const noexcept;
  };
  template<class R, class... ArgTypes>
    function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>;
  template<class F> function(F) -> function<see below>;
  // [func.wrap.func.nullptr], Null pointer comparisons
  template <class R, class... ArgTypes>
    bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
  template <class R, class... ArgTypes>
    bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
  template <class R, class... ArgTypes>
    bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
  template <class R, class... ArgTypes>
    bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
  // [func.wrap.func.alg], specialized algorithms
  template <class R, class... ArgTypes>
    void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept;
}function() noexcept;
function(nullptr_t) noexcept;
function(const function& f);
function(function&& f);
template<class F> function(F f);
template<class F> function(F) -> function<see below>;
function& operator=(const function& f);
function& operator=(function&& f);
function& operator=(nullptr_t) noexcept;
template<class F> function& operator=(F&& f);
template<class F> function& operator=(reference_wrapper<F> f) noexcept;
~function();
R operator()(ArgTypes... args) const;
const type_info& target_type() const noexcept;
template<class T>       T* target() noexcept;
template<class T> const T* target() const noexcept;
template <class R, class... ArgTypes>
  bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
  bool operator==(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
template <class R, class... ArgTypes>
  bool operator!=(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
  bool operator!=(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
template<class R, class... ArgTypes>
  void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;