Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix result type calculation for hpx::make_continuation #1619

Merged
merged 1 commit into from Jun 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 22 additions & 10 deletions hpx/runtime/actions/continuation.hpp
Expand Up @@ -17,6 +17,7 @@
#include <hpx/util/invoke.hpp>
#include <hpx/util/logging.hpp>
#include <hpx/util/demangle_helper.hpp>
#include <hpx/util/result_of.hpp>
#include <hpx/traits/is_action.hpp>
#include <hpx/traits/is_callable.hpp>
#include <hpx/traits/is_executor.hpp>
Expand Down Expand Up @@ -255,7 +256,7 @@ namespace hpx { namespace actions
template <typename F, typename T1, typename T2>
struct result<F(T1, T2)>
{
typedef T2 type;
typedef typename util::result_of<cont_type(T1, T2)>::type type;
};

continuation_impl() {}
Expand All @@ -268,13 +269,16 @@ namespace hpx { namespace actions
virtual ~continuation_impl() {}

template <typename T>
T operator()(hpx::id_type const& lco, T && t) const
typename result<continuation_impl(hpx::id_type, T)>::type
operator()(hpx::id_type const& lco, T && t) const
{
hpx::apply_c(cont_, lco, target_, std::forward<T>(t));

// Yep, 't' is a zombie, however we don't use the returned value
// anyways. We need it for result type calculation, though.
return std::move(t);
// Unfortunately we need to default construct the return value,
// this possibly imposes an additional restriction of return types.
typedef typename result<continuation_impl(hpx::id_type, T)>::type
result_type;
return result_type();
}

virtual bool has_to_wait_for_futures()
Expand Down Expand Up @@ -316,7 +320,12 @@ namespace hpx { namespace actions
template <typename This, typename T1, typename T2>
struct result<This(T1, T2)>
{
typedef T2 type;
typedef typename util::result_of<
cont_type(T1, T2)
>::type result_type;
typedef typename util::result_of<
function_type(hpx::id_type, result_type)
>::type type;
};

continuation2_impl() {}
Expand All @@ -332,15 +341,18 @@ namespace hpx { namespace actions
virtual ~continuation2_impl() {}

template <typename T>
T operator()(hpx::id_type const& lco, T && t) const
typename result<continuation2_impl(hpx::id_type, T)>::type
operator()(hpx::id_type const& lco, T && t) const
{
using hpx::util::placeholders::_2;
hpx::apply_continue(cont_, hpx::util::bind(f_, lco, _2),
target_, std::forward<T>(t));

// Yep, 't' is a zombie, however we don't use the returned value
// anyways. We need it for result type calculation, though.
return std::move(t);
// Unfortunately we need to default construct the return value,
// this possibly imposes an additional restriction of return types.
typedef typename result<continuation2_impl(hpx::id_type, T)>::type
result_type;
return result_type();
}

virtual bool has_to_wait_for_futures()
Expand Down
1 change: 1 addition & 0 deletions tests/regressions/actions/CMakeLists.txt
Expand Up @@ -6,6 +6,7 @@
add_subdirectory(components)

set(tests
make_continuation_1615
plain_action_1330
plain_action_1550
plain_action_move_semantics
Expand Down
43 changes: 43 additions & 0 deletions tests/regressions/actions/make_continuation_1615.cpp
@@ -0,0 +1,43 @@
// Copyright (c) 2015 Matthias Vill
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// Verify that #1615 was properly fixed (hpx::make_continuation requires input
// and output to be the same)

#include <hpx/hpx_init.hpp>
#include <hpx/include/actions.hpp>
#include <hpx/include/async.hpp>
#include <hpx/util/lightweight_test.hpp>

#include <boost/lexical_cast.hpp>

boost::int32_t times2(boost::int32_t i)
{
return i * 2;
}
HPX_PLAIN_ACTION(times2); // defines times2_action

std::string my_to_string(boost::int32_t i)
{
return boost::lexical_cast<std::string>(i);
}
HPX_PLAIN_ACTION(my_to_string); // defines to_string_action

int hpx_main(int argc, char* argv[])
{
std::string result = hpx::async_continue(
times2_action(), hpx::make_continuation(my_to_string_action()),
hpx::find_here(), 42).get();

HPX_TEST_EQ(result, std::string("84"));

return hpx::finalize();
}

int main(int argc, char* argv[])
{
HPX_TEST_EQ(hpx::init(argc, argv), 0);
return hpx::util::report_errors();
}