ParallelReduce( const FunctorType  & functor
                , const Policy       & policy
                , const HostViewType & result_view )
    : m_func( functor )
    , m_policy( policy )
    {
      QthreadExec::resize_worker_scratch( Reduce::value_size( m_func ) , 0 );

      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelReduce::execute , this );

      const pointer_type data = (pointer_type) QthreadExec::exec_all_reduce_result();

      Reduce::final( m_func , data );

      if ( result_view.ptr_on_device() ) {
        const unsigned n = Reduce::value_count( m_func );
        for ( unsigned i = 0 ; i < n ; ++i ) { result_view.ptr_on_device()[i] = data[i]; }
      }
    }
  ParallelReduce( const FunctorType  & functor ,
                  const Policy       & policy ,
                  const HostViewType & result_view )
    : m_func( functor )
    , m_policy( policy )
    {
      ThreadsExec::resize_reduce_scratch( Reduce::value_size( m_func ) );

      ThreadsExec::start( & ParallelReduce::execute , this );

      const pointer_type data = (pointer_type) ThreadsExec::root_reduce_scratch();

      ThreadsExec::fence();

      if ( result_view.ptr_on_device() ) {
        const unsigned n = Reduce::value_count( m_func );
        for ( unsigned i = 0 ; i < n ; ++i ) { result_view.ptr_on_device()[i] = data[i]; }
      }
    }
  ParallelReduce( const FunctorType  & arg_functor ,
                  const Policy       & arg_policy ,
                  const HostViewType & arg_result_view )
    : m_functor( arg_functor )
    , m_policy( arg_policy )
    , m_result_ptr( arg_result_view.ptr_on_device() )
    {
      static_assert( Kokkos::is_view< HostViewType >::value
        , "Kokkos::Threads reduce result must be a View" );

      static_assert( std::is_same< typename HostViewType::memory_space , HostSpace >::value
        , "Kokkos::Threads reduce result must be a View in HostSpace" );
    }