[Thread] 1.53 fails to compile working code
Hello,
following minimal code compiles fine with 1.52 and
BOOST_THREAD_VERSION defined to 3 but gives compilation error with
1.53 release (Visual Studio 2008 SP1, Win 7):
#include
Le 07/02/13 20:17, Szymon Gatner a écrit :
Hello,
following minimal code compiles fine with 1.52 and BOOST_THREAD_VERSION defined to 3 but gives compilation error with 1.53 release (Visual Studio 2008 SP1, Win 7):
#include
#include class Dummy { public:
Dummy& operator=(BOOST_RV_REF(Dummy) other);
Dummy& operator=(BOOST_COPY_ASSIGN_REF(Dummy) other);
BOOST_COPYABLE_AND_MOVABLE(Dummy); };
Dummy createDummy();
int main() { boost::future<Dummy> df = boost::async(&createDummy); } I suspect that the move constructor is missing
Dummy(BOOST_RV_REF(Dummy) other); and this should be removed I guess Dummy& operator=(BOOST_RV_REF(Dummy) other);
Btw: why BOOST_THREAD_VERSION is still 2 when documentation says it is 4.0.0 as of boost 1.53?
The documentation covers all the versions up to version 4.0.0. But the default version is 2 as requested in this ML, as version 3 introduced some not desired breaking changes. Best, Vicente
2013/2/7 Vicente J. Botet Escriba
I suspect that the move constructor is missing
Dummy(BOOST_RV_REF(Dummy) other);
Nope, it is not it. In fact my actual classes that cause errors do have moving c-tors.
and this should be removed I guess
Dummy& operator=(BOOST_RV_REF(Dummy) other);
This is necessary if class is movable and all our movable classes implement this operator. As I said before, all is good with 1.52 and this stops us from upgrading. Any other suggestions? Regards, Szymon Gatner
2013/2/7 Szymon Gatner
2013/2/7 Vicente J. Botet Escriba
: I suspect that the move constructor is missing
Dummy(BOOST_RV_REF(Dummy) other);
Nope, it is not it. In fact my actual classes that cause errors do have moving c-tors.
and this should be removed I guess
Dummy& operator=(BOOST_RV_REF(Dummy) other);
This is necessary if class is movable and all our movable classes implement this operator.
As I said before, all is good with 1.52 and this stops us from upgrading. Any other suggestions?
Actually custom movable class is not even needed. This all boost code
does not compile too:
#include
On Thu, Feb 7, 2013 at 11:17 AM, Szymon Gatner
Hello,
following minimal code compiles fine with 1.52 and BOOST_THREAD_VERSION defined to 3 but gives compilation error with 1.53 release (Visual Studio 2008 SP1, Win 7):
#include
#include class Dummy { public:
Dummy& operator=(BOOST_RV_REF(Dummy) other);
Dummy& operator=(BOOST_COPY_ASSIGN_REF(Dummy) other);
BOOST_COPYABLE_AND_MOVABLE(Dummy); };
Dummy createDummy();
int main() { boost::future<Dummy> df = boost::async(&createDummy); }
Error message:
1>------ Build started: Project: boost_153_test, Configuration: Debug Win32 ------ 1>Compiling... 1>main.cpp 1>c:\devel\boost_1_53_0\boost\thread\future.hpp(661) : error C2665: 'boost::detail::future_traits<T>::init' : none of the 2 overloads could convert all the argument types 1> with 1> [ 1> T=Dummy 1> ] 1> c:\devel\boost_1_53_0\boost\thread\future.hpp(525): could be 'void boost::detail::future_traits<T>::init(boost::scoped_ptr<T> &,Dummy &)' 1> with 1> [ 1> T=Dummy 1> ] 1> c:\devel\boost_1_53_0\boost\thread\future.hpp(530): or 'void boost::detail::future_traits<T>::init(boost::scoped_ptr<T> &,boost::rv<T> &)' 1> with 1> [ 1> T=Dummy 1> ] 1> while trying to match the argument list
This looks like an error in the future_traits<T>::init overload set...it's missing an overload that a T const & can bind to (in the second argument). Also, I think it would be an improvement if set_value_at_thread_exit was able to catch rvalues as emulated rvalue references (when true rvalue references are unavailable) rather than as lvalue-reference-to-const. - Jeff
2013/2/8 Jeffrey Lee Hellrung, Jr.
This looks like an error in the future_traits<T>::init overload set...it's missing an overload that a T const & can bind to (in the second argument).
Also, I think it would be an improvement if set_value_at_thread_exit was able to catch rvalues as emulated rvalue references (when true rvalue references are unavailable) rather than as lvalue-reference-to-const.
Yes indeed, there is an overload resolution ambiguity. I guess movable / emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move). Move already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate. Is the original move emulation even still needed in Thread code. It seems like half on BOOST_THREAD macros try to deal with move semantics. Regards, Simon
On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
2013/2/8 Jeffrey Lee Hellrung, Jr.
: This looks like an error in the future_traits<T>::init overload
set...it's
missing an overload that a T const & can bind to (in the second argument).
Also, I think it would be an improvement if set_value_at_thread_exit was able to catch rvalues as emulated rvalue references (when true rvalue references are unavailable) rather than as lvalue-reference-to-const.
Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's causing the compiler failure, it's that the eligible overload set is empty. I guess movable
/ emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move).
Yes :( I can imagine the maintenance nightmare for Vicente. Move
already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Ideally, but the present implementation of set_value_at_thread_exit precludes init capturing by rvalue reference, AFAICT.
Is the original move emulation even still needed in Thread code.
I think there are subtle differences, perhaps not all of which have been worked out or discovered yet. It
seems like half on BOOST_THREAD macros try to deal with move semantics.
- Jeff
Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
mailto:szymon.gatner@gmail.com> wrote: 2013/2/8 Jeffrey Lee Hellrung, Jr.
mailto:jeffrey.hellrung@gmail.com>: > > This looks like an error in the future_traits<T>::init overload set...it's > missing an overload that a T const & can bind to (in the second argument). > > Also, I think it would be an improvement if set_value_at_thread_exit was > able to catch rvalues as emulated rvalue references (when true rvalue > references are unavailable) rather than as lvalue-reference-to-const. > Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's causing the compiler failure, it's that the eligible overload set is empty. You are right.
I guess movable / emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move).
Yes :( I can imagine the maintenance nightmare for Vicente. I don't know if I've missed something really relevant of Boost.Move, but only with this emulation I have a lot of difficulties as not only Boost.Thread defines Movable types, but it offers interfaces with functions that can be movable and that accept copyable/movable arguments and that can return movable types.
Move already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Ideally, but the present implementation of set_value_at_thread_exit precludes init capturing by rvalue reference, AFAICT. Jeffrey I believe the problem comes from the fact that I have added two overloads for set_value_at_thread_exit and the copy overload is instantiated when using a move-only class
void set_value_at_thread_exit(const T & result_){...} // this instantiation with a MoveOnly class results in a compiler error void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_){...}
Is the original move emulation even still needed in Thread code.
Using Boost.Move is some kind of breaking change respect to the old one. I'm fully for discarding the old emulation, but I would like to hear what others thing.
I think there are subtle differences, perhaps not all of which have been worked out or discovered yet.
I don't think the problem comes from trying to manage 2 move emulations, but of course I might be wrong. anyway, I will see if I can fix it or otherwise I would restraint the use of _at_thread_exit functions to the compilers supporting them completely. Thanks for the report, Vicente
On Fri, Feb 8, 2013 at 1:31 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
wrote: 2013/2/8 Jeffrey Lee Hellrung, Jr.
: This looks like an error in the future_traits<T>::init overload
set...it's
missing an overload that a T const & can bind to (in the second argument).
Also, I think it would be an improvement if set_value_at_thread_exit was able to catch rvalues as emulated rvalue references (when true rvalue references are unavailable) rather than as lvalue-reference-to-const.
Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's causing the compiler failure, it's that the eligible overload set is empty.
You are right.
I guess movable
/ emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move).
Yes :( I can imagine the maintenance nightmare for Vicente.
I don't know if I've missed something really relevant of Boost.Move, but only with this emulation I have a lot of difficulties as not only Boost.Thread defines Movable types, but it offers interfaces with functions that can be movable and that accept copyable/movable arguments and that can return movable types.
Move
already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Ideally, but the present implementation of set_value_at_thread_exit precludes init capturing by rvalue reference, AFAICT.
Jeffrey I believe the problem comes from the fact that I have added two overloads for set_value_at_thread_exit and the copy overload is instantiated when using a move-only class
void set_value_at_thread_exit(const T & result_){...} // this instantiation with a MoveOnly class results in a compiler error void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_){...}
Is the original move emulation even still needed in Thread code.
Using Boost.Move is some kind of breaking change respect to the old one. I'm fully for discarding the old emulation, but I would like to hear what others thing.
I think there are subtle differences, perhaps not all of which have been worked out or discovered yet.
I don't think the problem comes from trying to manage 2 move emulations, but of course I might be wrong.
anyway, I will see if I can fix it or otherwise I would restraint the use of _at_thread_exit functions to the compilers supporting them completely.
Vicente, here's some tips on how to improve the robustness of the code when compiling without rvalue references (i.e., C++03): If you know a function is going to receive only lvalues or *emulated* rvalue references, it's sufficient to use a T & parameter: [[template< class T > void f(T & x);]] (Just be careful you don't accidentally move x; you may need to wrap some uses of x as [[as_lvalue(x)]] to avoid that.) This is the appropriate case for functions that receive results of boost::forward; I think future_traits::init falls in this category. If a function is designed to accept both lvalues *and* rvalues *of an a priori known type T*, and you want to be able to capture rvalues by emulated rvalue reference (when appropriate), then you need have 2 cases: - T is not Boost.Move-enabled: 1 overload is probably sufficient (if you don't care about constness): [[void f(T const &);]] - T is Boost.Move-enabled: 2 overloads are necessary: [[void f(rv<T> &);]] and [[template< class U > void f(U &);]] Lastly, if a function is designed to accept both lvalues and rvalues of *any* type, and you want to be able to capture any rvalue by emulated rvalue reference when possible, you need 3 overloads, and even then it's not always possible (if the function return type depends on the parameter type, you're probably SOL). This is much more involved, so I won't go into detail here, as I think the issues relevant to this thread fall into one of the two cases above. If you want more detailed help (e.g., patches), we can take this offline. - Jeff
Le 09/02/13 00:13, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Feb 8, 2013 at 1:31 PM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
mailto:szymon.gatner@gmail.com> wrote: 2013/2/8 Jeffrey Lee Hellrung, Jr.
mailto:jeffrey.hellrung@gmail.com>: > > This looks like an error in the future_traits<T>::init overload set...it's > missing an overload that a T const & can bind to (in the second argument). > > Also, I think it would be an improvement if set_value_at_thread_exit was > able to catch rvalues as emulated rvalue references (when true rvalue > references are unavailable) rather than as lvalue-reference-to-const. > Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's causing the compiler failure, it's that the eligible overload set is empty.
You are right.
I guess movable / emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move).
Yes :( I can imagine the maintenance nightmare for Vicente.
I don't know if I've missed something really relevant of Boost.Move, but only with this emulation I have a lot of difficulties as not only Boost.Thread defines Movable types, but it offers interfaces with functions that can be movable and that accept copyable/movable arguments and that can return movable types.
Move already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Ideally, but the present implementation of set_value_at_thread_exit precludes init capturing by rvalue reference, AFAICT.
Jeffrey I believe the problem comes from the fact that I have added two overloads for set_value_at_thread_exit and the copy overload is instantiated when using a move-only class
void set_value_at_thread_exit(const T & result_){...} // this instantiation with a MoveOnly class results in a compiler error void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_){...}
Is the original move emulation even still needed in Thread code.
Using Boost.Move is some kind of breaking change respect to the old one. I'm fully for discarding the old emulation, but I would like to hear what others thing.
I think there are subtle differences, perhaps not all of which have been worked out or discovered yet.
I don't think the problem comes from trying to manage 2 move emulations, but of course I might be wrong.
anyway, I will see if I can fix it or otherwise I would restraint the use of _at_thread_exit functions to the compilers supporting them completely.
Vicente, here's some tips on how to improve the robustness of the code when compiling without rvalue references (i.e., C++03):
If you know a function is going to receive only lvalues or *emulated* rvalue references, it's sufficient to use a T & parameter: [[template< class T > void f(T & x);]] (Just be careful you don't accidentally move x; you may need to wrap some uses of x as [[as_lvalue(x)]] to avoid that.) This is the appropriate case for functions that receive results of boost::forward; I think future_traits::init falls in this category.
If a function is designed to accept both lvalues *and* rvalues *of an a priori known type T*, and you want to be able to capture rvalues by emulated rvalue reference (when appropriate), then you need have 2 cases: - T is not Boost.Move-enabled: 1 overload is probably sufficient (if you don't care about constness): [[void f(T const &);]] - T is Boost.Move-enabled: 2 overloads are necessary: [[void f(rv<T> &);]] and [[template< class U > void f(U &);]]
Lastly, if a function is designed to accept both lvalues and rvalues of *any* type, and you want to be able to capture any rvalue by emulated rvalue reference when possible, you need 3 overloads, and even then it's not always possible (if the function return type depends on the parameter type, you're probably SOL). This is much more involved, so I won't go into detail here, as I think the issues relevant to this thread fall into one of the two cases above.
If you want more detailed help (e.g., patches), we can take this offline.
Hi, I have reached to make it compile, but I suspect that there is yet a race condition as the test fail/pass randomly. See attached the patch. Jeffrey any help on this will be really welcome. Contact me offline if you get something. Thanks, Vicente
Le 09/02/13 00:41, Vicente J. Botet Escriba a écrit :
Le 09/02/13 00:13, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Feb 8, 2013 at 1:31 PM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
On Thu, Feb 7, 2013 at 11:46 PM, Szymon Gatner
mailto:szymon.gatner@gmail.com> wrote: 2013/2/8 Jeffrey Lee Hellrung, Jr.
mailto:jeffrey.hellrung@gmail.com>: > > This looks like an error in the future_traits<T>::init overload set...it's > missing an overload that a T const & can bind to (in the second argument). > > Also, I think it would be an improvement if set_value_at_thread_exit was > able to catch rvalues as emulated rvalue references (when true rvalue > references are unavailable) rather than as lvalue-reference-to-const. > Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's causing the compiler failure, it's that the eligible overload set is empty.
You are right.
I guess movable / emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move).
Yes :( I can imagine the maintenance nightmare for Vicente.
I don't know if I've missed something really relevant of Boost.Move, but only with this emulation I have a lot of difficulties as not only Boost.Thread defines Movable types, but it offers interfaces with functions that can be movable and that accept copyable/movable arguments and that can return movable types.
Move already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Ideally, but the present implementation of set_value_at_thread_exit precludes init capturing by rvalue reference, AFAICT.
Jeffrey I believe the problem comes from the fact that I have added two overloads for set_value_at_thread_exit and the copy overload is instantiated when using a move-only class
void set_value_at_thread_exit(const T & result_){...} // this instantiation with a MoveOnly class results in a compiler error void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_){...}
Is the original move emulation even still needed in Thread code.
Using Boost.Move is some kind of breaking change respect to the old one. I'm fully for discarding the old emulation, but I would like to hear what others thing.
I think there are subtle differences, perhaps not all of which have been worked out or discovered yet.
I don't think the problem comes from trying to manage 2 move emulations, but of course I might be wrong.
anyway, I will see if I can fix it or otherwise I would restraint the use of _at_thread_exit functions to the compilers supporting them completely.
Vicente, here's some tips on how to improve the robustness of the code when compiling without rvalue references (i.e., C++03):
If you know a function is going to receive only lvalues or *emulated* rvalue references, it's sufficient to use a T & parameter: [[template< class T > void f(T & x);]] (Just be careful you don't accidentally move x; you may need to wrap some uses of x as [[as_lvalue(x)]] to avoid that.) This is the appropriate case for functions that receive results of boost::forward; I think future_traits::init falls in this category.
If a function is designed to accept both lvalues *and* rvalues *of an a priori known type T*, and you want to be able to capture rvalues by emulated rvalue reference (when appropriate), then you need have 2 cases: - T is not Boost.Move-enabled: 1 overload is probably sufficient (if you don't care about constness): [[void f(T const &);]] - T is Boost.Move-enabled: 2 overloads are necessary: [[void f(rv<T> &);]] and [[template< class U > void f(U &);]]
Lastly, if a function is designed to accept both lvalues and rvalues of *any* type, and you want to be able to capture any rvalue by emulated rvalue reference when possible, you need 3 overloads, and even then it's not always possible (if the function return type depends on the parameter type, you're probably SOL). This is much more involved, so I won't go into detail here, as I think the issues relevant to this thread fall into one of the two cases above.
If you want more detailed help (e.g., patches), we can take this offline.
Hi,
I have reached to make it compile, but I suspect that there is yet a race condition as the test fail/pass randomly.
See attached the patch.
Jeffrey any help on this will be really welcome. Contact me offline if you get something.
I have made some updates to future.hpp and now the two tests work correctly. I don't know if all the modifications are absolutely needed. Please, could you give it a try? Thanks, Vicente
2013/2/10 Vicente J. Botet Escriba
I have made some updates to future.hpp and now the two tests work correctly. I don't know if all the modifications are absolutely needed.
Please, could you give it a try?
Original test code compiles OK now but unfortunately fails in other place:
#include
Le 10/02/13 12:36, Szymon Gatner a écrit :
2013/2/10 Vicente J. Botet Escriba
: I have made some updates to future.hpp and now the two tests work correctly. I don't know if all the modifications are absolutely needed.
Please, could you give it a try?
Original test code compiles OK now but unfortunately fails in other place:
#include
#include typedef boost::container::vector<int> V;
int main() { boost::future<V> vf; V v(boost::move(vf.get())); // fails to compile // also fails: V v = boost::move(vf.get()) }
vf.get() returns a rvalue and so boost::move doesn't work. You should use V v(vf.get()); Best, Vicente
Le 10/02/13 11:08, Vicente J. Botet Escriba a écrit :
Le 09/02/13 00:41, Vicente J. Botet Escriba a écrit :
Hi,
I have reached to make it compile, but I suspect that there is yet a race condition as the test fail/pass randomly.
See attached the patch.
Jeffrey any help on this will be really welcome. Contact me offline if you get something.
I have made some updates to future.hpp and now the two tests work correctly. I don't know if all the modifications are absolutely needed.
I have committed the modifications on trunk. Committed revision 82808. Hopping this would not break too much code, Vicente
Le 08/02/13 08:46, Szymon Gatner a écrit :
2013/2/8 Jeffrey Lee Hellrung, Jr.
: This looks like an error in the future_traits<T>::init overload set...it's missing an overload that a T const & can bind to (in the second argument).
Also, I think it would be an improvement if set_value_at_thread_exit was able to catch rvalues as emulated rvalue references (when true rvalue references are unavailable) rather than as lvalue-reference-to-const.
Yes indeed, there is an overload resolution ambiguity. I guess movable / emulation stuff in Thread is more difficult to manage since it maintains 2 move emulations (original one from Thread and Move). Move already provides BOOST_RV_REF(T) macro which is T&& on compiler that support it and rv<T>& when emulating and this imho is the argument type future_traits<T>::init() should use to disambiguate.
Is the original move emulation even still needed in Thread code. It seems like half on BOOST_THREAD macros try to deal with move semantics.
Hi, please could you create a Trac ticket? Thanks, Vicente
participants (3)
-
Jeffrey Lee Hellrung, Jr.
-
Szymon Gatner
-
Vicente J. Botet Escriba