Hi!

Build failure after trunk r241093:
    
[...]/source-gcc/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc:121:12: 
error: ISO C++ forbids declaration of '_Bind_simple_helper' with no type 
[-fpermissive]
       template _Bind_simple_helper<void (thread::*)(), 
reference_wrapper<thread>>::__type __bind_simple(void (thread::*&&)(), 
reference_wrapper<thread>&&);
                ^~~~~~~~~~~~~~~~~~~
    
[...]/source-gcc/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc:121:12: 
error: '_Bind_simple_helper' is not a template function
    
[...]/source-gcc/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc:121:31: 
error: expected ';' before '<' token
       template _Bind_simple_helper<void (thread::*)(), 
reference_wrapper<thread>>::__type __bind_simple(void (thread::*&&)(), 
reference_wrapper<thread>&&);
                                   ^

For reference:

On Thu, 13 Oct 2016 11:37:06 +0100, Jonathan Wakely <jwak...@redhat.com> wrote:
> Some time ago I added __bind_simple, which is a simpler version of
> std::bind that doesn't support placeholders and nested bind
> expressions. It's only needed by a few concurrency components that do
> INVOKE(DECAY_COPY(f), DECAY_COPY(args)...) but those conponents have
> to include the whole of <functional> to get it.
> 
> Now that std::call_once() doesn't use it, it's only needed in <thread>
> and <future> so I'm moving it into <thread>, renaming it to
> std::thread::__make_invoker, and adding some comments about its
> purpose.
> 
> std::packaged_task shouldn't be using that function anyway, because it
> doesn't want the DECAY_COPY semantics and I was forced to wrap the
> arguments in reference_wrappers to prevent the decaying. Like
> std::call_once it can just use a lambda-expression instead.
> 
> This allows us to remove <functional> from <thread> and <future>. That
> doesn't reduce the size of preprocessed source yet, because <memory>
> includes the whole of <functional> anyway, but I'll reduce that soon.
> 
>       * include/std/functional (_Bind_simple, _Bind_simple_helper)
>       (__bind_simple): Remove.
>       * include/std/future: Include <bits/invoke.h> instead of <functional>.
>       (__future_base::_Task_state::_M_run)
>       (__future_base::_Task_state::_M_run_delayed): Use lambda expressions
>       instead of __bind_simple.
>       (__future_base::_Task_state::_S_maybe_wrap_ref): Remove.
>       (async): Use thread::__make_invoker instead of __bind_simple.
>       * include/std/thread: Include <tuple> and <bits/invoke.h> instead of
>       <functional>.
>       (thread::_Invoker, thread::__make_invoker): Define helpers to do
>       INVOKE(DECAY_COPY(f), DECAY_COPY(args)...).
> 
> Tested powerpc64le-linux, committed to trunk.
> 
> commit 13c071f6ee2e3edb177e6150f7a3903ecaf9de68
> Author: Jonathan Wakely <jwak...@redhat.com>
> Date:   Wed Oct 12 17:15:46 2016 +0100
> 
>     Replace __bind_simple with std::thread::__make_invoker
>     
>       * include/std/functional (_Bind_simple, _Bind_simple_helper)
>       (__bind_simple): Remove.
>       * include/std/future: Include <bits/invoke.h> instead of <functional>.
>       (__future_base::_Task_state::_M_run)
>       (__future_base::_Task_state::_M_run_delayed): Use lambda expressions
>       instead of __bind_simple.
>       (__future_base::_Task_state::_S_maybe_wrap_ref): Remove.
>       (async): Use thread::__make_invoker instead of __bind_simple.
>       * include/std/thread: Include <tuple> and <bits/invoke.h> instead of
>       <functional>.
>       (thread::_Invoker, thread::__make_invoker): Define helpers to do
>       INVOKE(DECAY_COPY(f), DECAY_COPY(args)...).
> 
> diff --git a/libstdc++-v3/include/std/functional 
> b/libstdc++-v3/include/std/functional
> index 58134b7..3877033 100644
> --- a/libstdc++-v3/include/std/functional
> +++ b/libstdc++-v3/include/std/functional
> @@ -1300,69 +1300,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
>                          std::forward<_BoundArgs>(__args)...);
>      }
>  
> -  template<typename _Signature>
> -    struct _Bind_simple;
> -
> -  template<typename _Callable, typename... _Args>
> -    struct _Bind_simple<_Callable(_Args...)>
> -    {
> -      typedef typename result_of<_Callable(_Args...)>::type result_type;
> -
> -      template<typename _Tp, typename... _Up>
> -        explicit
> -        _Bind_simple(_Tp&& __f, _Up&&... __args)
> -        : _M_bound(std::forward<_Tp>(__f), std::forward<_Up>(__args)...)
> -        { }
> -
> -      _Bind_simple(const _Bind_simple&) = default;
> -      _Bind_simple(_Bind_simple&&) = default;
> -
> -      result_type
> -      operator()()
> -      {
> -        typedef typename _Build_index_tuple<sizeof...(_Args)>::__type 
> _Indices;
> -        return _M_invoke(_Indices());
> -      }
> -
> -    private:
> -      template<std::size_t... _Indices>
> -        typename result_of<_Callable(_Args...)>::type
> -        _M_invoke(_Index_tuple<_Indices...>)
> -        {
> -       // std::bind always forwards bound arguments as lvalues,
> -       // but this type can call functions which only accept rvalues.
> -          return std::forward<_Callable>(std::get<0>(_M_bound))(
> -              std::forward<_Args>(std::get<_Indices+1>(_M_bound))...);
> -        }
> -
> -      std::tuple<_Callable, _Args...> _M_bound;
> -    };
> -
> -  template<typename _Func, typename... _BoundArgs>
> -    struct _Bind_simple_helper
> -    : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
> -    {
> -      typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
> -        __maybe_type;
> -      typedef typename __maybe_type::type __func_type;
> -      typedef _Bind_simple<__func_type(typename decay<_BoundArgs>::type...)>
> -             __type;
> -    };
> -
> -  // Simplified version of std::bind for internal use, without support for
> -  // unbound arguments, placeholders or nested bind expressions.
> -  template<typename _Callable, typename... _Args>
> -    typename _Bind_simple_helper<_Callable, _Args...>::__type
> -    __bind_simple(_Callable&& __callable, _Args&&... __args)
> -    {
> -      typedef _Bind_simple_helper<_Callable, _Args...> __helper_type;
> -      typedef typename __helper_type::__maybe_type __maybe_type;
> -      typedef typename __helper_type::__type __result_type;
> -      return __result_type(
> -          __maybe_type::__do_wrap( std::forward<_Callable>(__callable)),
> -          std::forward<_Args>(__args)...);
> -    }
> -
>    /**
>     *  @brief Exception class thrown when class template function's
>     *  operator() is called with an empty target.
> diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
> index aa866c5..fffbdbb 100644
> --- a/libstdc++-v3/include/std/future
> +++ b/libstdc++-v3/include/std/future
> @@ -35,7 +35,6 @@
>  # include <bits/c++0x_warning.h>
>  #else
>  
> -#include <functional>
>  #include <mutex>
>  #include <thread>
>  #include <condition_variable>
> @@ -43,6 +42,7 @@
>  #include <atomic>
>  #include <bits/atomic_futex.h>
>  #include <bits/functexcept.h>
> +#include <bits/invoke.h>
>  #include <bits/unique_ptr.h>
>  #include <bits/shared_ptr.h>
>  #include <bits/uses_allocator.h>
> @@ -1403,18 +1403,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        virtual void
>        _M_run(_Args&&... __args)
>        {
> -     // bound arguments decay so wrap lvalue references
> -     auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
> -         _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
> +     auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
> +         return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
> +     };
>       this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
>        }
>  
>        virtual void
>        _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
>        {
> -     // bound arguments decay so wrap lvalue references
> -     auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
> -         _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
> +     auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
> +         return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
> +     };
>       this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
>                                   std::move(__self));
>        }
> @@ -1422,17 +1422,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        virtual shared_ptr<_Task_state_base<_Res(_Args...)>>
>        _M_reset();
>  
> -      template<typename _Tp>
> -     static reference_wrapper<_Tp>
> -     _S_maybe_wrap_ref(_Tp& __t)
> -     { return std::ref(__t); }
> -
> -      template<typename _Tp>
> -     static
> -     typename enable_if<!is_lvalue_reference<_Tp>::value, _Tp>::type&&
> -     _S_maybe_wrap_ref(_Tp&& __t)
> -     { return std::forward<_Tp>(__t); }
> -
>        struct _Impl : _Alloc
>        {
>       template<typename _Fn2>
> @@ -1713,8 +1702,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       {
>         __try
>           {
> -           __state = __future_base::_S_make_async_state(std::__bind_simple(
> -               std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
> +           __state = __future_base::_S_make_async_state(
> +               std::thread::__make_invoker(std::forward<_Fn>(__fn),
> +                                           std::forward<_Args>(__args)...)
> +               );
>           }
>  #if __cpp_exceptions
>         catch(const system_error& __e)
> @@ -1727,8 +1718,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       }
>        if (!__state)
>       {
> -       __state = __future_base::_S_make_deferred_state(std::__bind_simple(
> -              std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
> +       __state = __future_base::_S_make_deferred_state(
> +           std::thread::__make_invoker(std::forward<_Fn>(__fn),
> +                                       std::forward<_Args>(__args)...));
>       }
>        return future<__async_result_of<_Fn, _Args...>>(__state);
>      }
> diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
> index 7e185d3..7a3c407 100644
> --- a/libstdc++-v3/include/std/thread
> +++ b/libstdc++-v3/include/std/thread
> @@ -36,11 +36,12 @@
>  #else
>  
>  #include <chrono>
> -#include <functional>
>  #include <memory>
> +#include <tuple>
>  #include <cerrno>
>  #include <bits/functexcept.h>
>  #include <bits/functional_hash.h>
> +#include <bits/invoke.h>
>  #include <bits/gthr.h>
>  
>  #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
> @@ -122,8 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       auto __depend = nullptr;
>  #endif
>          _M_start_thread(_S_make_state(
> -           std::__bind_simple(std::forward<_Callable>(__f),
> -                              std::forward<_Args>(__args)...)),
> +           __make_invoker(std::forward<_Callable>(__f),
> +                          std::forward<_Args>(__args)...)),
>           __depend);
>        }
>  
> @@ -212,6 +213,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      void
>      _M_start_thread(__shared_base_type);
>  #endif
> +
> +  private:
> +    // A call wrapper that does INVOKE(forwarded tuple elements...)
> +    template<typename _Tuple>
> +      struct _Invoker
> +      {
> +     _Tuple _M_t;
> +
> +     template<size_t _Index>
> +       static __tuple_element_t<_Index, _Tuple>&&
> +       _S_declval();
> +
> +     template<size_t... _Ind>
> +       auto
> +       _M_invoke(_Index_tuple<_Ind...>)
> +       noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
> +       -> decltype(std::__invoke(_S_declval<_Ind>()...))
> +       { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
> +
> +     using _Indices
> +       = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
> +
> +     using result_type
> +       = decltype(std::declval<_Invoker>()._M_invoke(_Indices()));
> +
> +     result_type
> +     operator()()
> +     noexcept(noexcept(std::declval<_Invoker>()._M_invoke(_Indices())))
> +     { return _M_invoke(_Indices()); }
> +
> +      };
> +
> +    // Alias for _Invoker<tuple<DECAY_COPY(_Tp)...>>
> +    template<typename... _Tp>
> +      using __invoker_type
> +     = _Invoker<decltype(std::make_tuple(std::declval<_Tp>()...))>;
> +
> +  public:
> +    // Returns a call wrapper that does
> +    // INVOKE(DECAY_COPY(__callable), DECAY_COPY(__args)).
> +    template<typename _Callable, typename... _Args>
> +      static __invoker_type<_Callable, _Args...>
> +      __make_invoker(_Callable&& __callable, _Args&&... __args)
> +      {
> +     return { {
> +         std::make_tuple(std::forward<_Callable>(__callable),
> +                         std::forward<_Args>(__args)...)
> +     } };
> +      }
>    };
>  
>    inline void


Grüße
 Thomas

Reply via email to