Opened 8 years ago

Closed 8 years ago

#10340 closed Bugs (fixed)

No boost::promise<T>::set_value(const T&) overload present in C++03 mode

Reported by: rob.desbois@… Owned by: viboes
Milestone: Boost 1.57.0 Component: thread
Version: Boost 1.54.0 Severity: Problem
Keywords: Cc:

Description (last modified by viboes)

When compiling in C++03 mode I am unable to use anything but a primitive type in a promise, and therefore also the dependent types in Boost.Thread

Minimal testcase:

    #include <boost/thread/future.hpp>

    struct foo
    {
        foo(int i_): i(i_) {}
        int i;
    };

    int main()
    {
        // Clearly a const future ref isn't much use, but I needed to
        // prove the problem wasn't me trying to copy a unique_future

        const boost::unique_future<foo>& fut = boost::make_ready_future( foo(42) );
    }

Output from g++ 4.8.2 with Boost 1.55 and -DBOOST_THREAD_USES_MOVE:

In file included from ../../deps/boost/include/boost/tuple/tuple.hpp:33:0,

from ../../deps/boost/include/boost/thread/detail/async_func.hpp:37, from ../../deps/boost/include/boost/thread/future.hpp:22, from t.cpp:2:

../../deps/boost/include/boost/tuple/detail/tuple_basic.hpp: In function ‘typename boost::tuples::access_traits<typename boost::tuples::element<N, boost::tuples::cons<HT, TT> >::type>::const_type boost::tuples::get(const boost::tuples::cons<HT, TT>&)’: ../../deps/boost/include/boost/tuple/detail/tuple_basic.hpp:228:45: warning: typedef ‘cons_element’ locally defined but not used [-Wunused-local-typedefs]

typedef BOOST_DEDUCED_TYPENAME impl::type cons_element;

In file included from ../../deps/boost/include/boost/bind/bind.hpp:29:0,

from ../../deps/boost/include/boost/bind.hpp:22, from ../../deps/boost/include/boost/thread/future.hpp:41, from t.cpp:2:

../../deps/boost/include/boost/bind/arg.hpp: In constructor ‘boost::arg<I>::arg(const T&)’: ../../deps/boost/include/boost/bind/arg.hpp:37:22: warning: typedef ‘T_must_be_placeholder’ locally defined but not used [-Wunused-local-typedefs]

typedef char T_must_be_placeholder[ I == is_placeholder<T>::value? 1: -1 ];

t.cpp: In function ‘int main()’: t.cpp:12:78: error: expected primary-expression before ‘f’

const boost::unique_future<foo>& fut = boost::make_ready_future( foo f(42) );

t.cpp:12:42: warning: unused variable ‘fut’ [-Wunused-variable]

const boost::unique_future<foo>& fut = boost::make_ready_future( foo f(42) );

In file included from ../../deps/boost/include/boost/system/system_error.hpp:14:0,

from ../../deps/boost/include/boost/thread/exceptions.hpp:22, from ../../deps/boost/include/boost/thread/pthread/mutex.hpp:12, from ../../deps/boost/include/boost/thread/mutex.hpp:16, from ../../deps/boost/include/boost/thread/future.hpp:24, from t.cpp:2:

../../deps/boost/include/boost/system/error_code.hpp: At global scope: ../../deps/boost/include/boost/system/error_code.hpp:222:36: warning: ‘boost::system::posix_category’ defined but not used [-Wunused-variable]

static const error_category & posix_category = generic_category();

../../deps/boost/include/boost/system/error_code.hpp:223:36: warning: ‘boost::system::errno_ecat’ defined but not used [-Wunused-variable]

static const error_category & errno_ecat = generic_category();

../../deps/boost/include/boost/system/error_code.hpp:224:36: warning: ‘boost::system::native_ecat’ defined but not used [-Wunused-variable]

static const error_category & native_ecat = system_category();

I have replicated this with Clang 3.4, also with Boost 1.54 on both compilers, and without -DBOOST_THREAD_USES_MOVE too. From the boost-users mailing list it looks like it has been replicated with 1.56 too.

Change History (12)

comment:1 by anonymous, 8 years ago

The error you pasted is due to a syntax error and doesn't match the code you pasted:

t.cpp: In function ‘int main()’: t.cpp:12:78: error: expected primary-expression before ‘f’

const boost::unique_future<foo>& fut = boost::make_ready_future( foo f(42) );

(Also the output would be a lot more useful with -Wno-unused-local-typedefs)

comment:2 by anonymous, 8 years ago

Simpler test case:

#include <boost/thread/future.hpp>

struct foo {
  foo(int i_) { }
};

int main() {

  boost::promise<foo> p;
  const foo f(42);
  p.set_value(f);
}

This fails with -DBOOST_THREAD_USES_MOVE but compiles OK without.

comment:3 by rob.desbois@…, 8 years ago

Agh, apologies for the brainfail there. Problem hopefully clear from the bug title, but for completeness here is the compile error with 1.55, g++ 4.8.2, and -DBOOST_THREAD_USES_MOVE:

In file included from t.cpp:1:0:
../deps/boost/include/boost/thread/future.hpp: In instantiation of ‘boost::unique_future<typename boost::decay<T>::type> boost::make_ready_future(const T&) [with T = foo; typename boost::decay<T>::type = foo]’:
t.cpp:14:35:   required from here
../deps/boost/include/boost/thread/future.hpp:3634:5: error: no matching function for call to ‘boost::promise<foo>::set_value(const foo&)’
     p.set_value(boost::forward<future_value_type>(value));
     ^
../deps/boost/include/boost/thread/future.hpp:3634:5: note: candidates are:
In file included from t.cpp:1:0:
../deps/boost/include/boost/thread/future.hpp:2052:14: note: void boost::promise<R>::set_value(typename boost::detail::future_traits<T>::source_reference_type) [with R = foo; typename boost::detail::future_traits<T>::source_reference_type = foo&]
         void set_value(typename detail::future_traits<R>::source_reference_type r)
              ^
../deps/boost/include/boost/thread/future.hpp:2052:14: note:   no known conversion for argument 1 from ‘const foo’ to ‘boost::detail::future_traits<foo>::source_reference_type {aka foo&}’
../deps/boost/include/boost/thread/future.hpp:2064:14: note: void boost::promise<R>::set_value(typename boost::detail::future_traits<T>::rvalue_source_type) [with R = foo; typename boost::detail::future_traits<T>::rvalue_source_type = boost::rv<foo>&]
         void set_value(typename detail::future_traits<R>::rvalue_source_type r)
              ^
../deps/boost/include/boost/thread/future.hpp:2064:14: note:   no known conversion for argument 1 from ‘const foo’ to ‘boost::detail::future_traits<foo>::rvalue_source_type {aka boost::rv<foo>&}’

comment:4 by viboes, 8 years ago

IIUC you need to make foo movable in C++98 compilers.

in reply to:  4 comment:5 by viboes, 8 years ago

Replying to viboes:

IIUC you need to make foo movable in C++98 compilers.

Forget this comment, please :(

comment:6 by viboes, 8 years ago

Description: modified (diff)

comment:7 by viboes, 8 years ago

Description: modified (diff)

comment:8 by viboes, 8 years ago

Please, could you tell me if the following patch works for you

git diff ../include/boost/thread/future.hpp
diff --git a/include/boost/thread/future.hpp b/include/boost/thread/future.hpp
index 184d305..c7e81d5 100644
--- a/include/boost/thread/future.hpp
+++ b/include/boost/thread/future.hpp
@@ -553,7 +553,7 @@ namespace boost
           //typedef typename conditional<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
           typedef T move_dest_type;
 #elif defined BOOST_THREAD_USES_MOVE
-          typedef typename conditional<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
+          typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
           //typedef typename conditional<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
           //typedef typename conditional<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
           typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;

comment:10 by rob.desbois@…, 8 years ago

It does indeed; thanks viboes.

comment:11 by viboes, 8 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:12 by viboes, 8 years ago

Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.