Opened 8 years ago

Closed 8 years ago

#10125 closed Bugs (fixed)

call_once: compile errors in variadic version with rvalue reference emulation

Reported by: raad@… Owned by: viboes
Milestone: Boost 1.56.0 Component: thread
Version: Boost 1.55.0 Severity: Problem
Keywords: Cc: raad@…

Description

In the variadic template version, boost::call_once uses BOOST_THREAD_RV_REF for the function and function argument parameters.

If the Boost.Move rvalue reference emulation is active, this only compiles for classes that use one of the macros in Boost.Move in their class definiton. Notably, it dooes not compile for Boost.Bind and Boost.Function objects.

Could this be changed to use BOOST_THREAD_FWD_REF instead of BOOST_THREAD_RV_REF or could const& overloads be added?

Attachments (2)

boost_call_once_test.zip (3.0 KB ) - added by raad@… 8 years ago.
Poject showing the error for MSVC12
call_once_variadic.patch (2.6 KB ) - added by raad@… 8 years ago.

Download all attachments as: .zip

Change History (15)

comment:1 by viboes, 8 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

Please, could you show an example an the compile error?

comment:2 by raad@…, 8 years ago

Please see the attached simple example for MSVC12. The error message is:

boost_call_once_test\boost_call_once_test\boost_call_once_test.cpp(19): error C2665: 'boost::call_once' : none of the 2 overloads could convert all the argument types
1>          boost_call_once_test\boost_call_once_test\boost\thread\win32\once.hpp(232): could be 'void boost::call_once(boost::once_flag &,void (__cdecl *)(void))'
1>          boost_call_once_test\boost_call_once_test\boost\thread\once.hpp(35): or       'void boost::call_once<boost::once_flag>(Function,boost::once_flag &)'
1>          with
1>          [
1>              Function=boost::once_flag
1>          ]
1>          while trying to match the argument list '(boost::once_flag, boost::_bi::bind_t<void,boost::_mfi::mf0<void,test_class>,boost::_bi::list1<boost::_bi::value<T>>>)'
1>          with
1>          [
1>              T=test_class
1>          ]

I don't know why the error message doesn't even mention

void call_once<Function>(once_flag& flag, boost::rv<Function> &f)

, IntelliSense suggests that overload too.

clang gives similar errors.

by raad@…, 8 years ago

Attachment: boost_call_once_test.zip added

Poject showing the error for MSVC12

comment:3 by viboes, 8 years ago

I have reached to make it work with

#define BOOST_THREAD_VERSION 4
//#define BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_PROVIDES_ONCE_CXX11

I don't remember why BOOST_THREAD_PROVIDES_ONCE_CXX11 is not defined when BOOST_THREAD_VERSION is defined.

Please could you check if this work for you. I will comeback when I found why I have not defined it.

comment:4 by viboes, 8 years ago

I have found this comment

// For C++11 call_once interface the compiler MUST support constexpr.
// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe.
#if defined(BOOST_THREAD_PROVIDES_ONCE_CXX11)
#if defined(BOOST_NO_CXX11_CONSTEXPR)
#undef BOOST_THREAD_PROVIDES_ONCE_CXX11
#endif
#endif

And

#if BOOST_THREAD_VERSION>=3

// ONCE_CXX11
// fixme BOOST_THREAD_PROVIDES_ONCE_CXX11 doesn't works when thread.cpp is compiled BOOST_THREAD_VERSION 3
#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \
 && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11
#define BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
#endif

I will comeback with more insight.

comment:5 by raad@…, 8 years ago

Defining BOOST_THREAD_PROVIDES_ONCE_CXX11 would work for me as I don't actually need this for MSVC, only for the latest clang. I only use MSVC for testing as I don't have access to clang regularly. But unfortunately I still have to define BOOST_NO_CXX11_RVALUE_REFERENCES as the standard library I have to use with clang is not move-aware and does not provide std::move and std::forward :-(

comment:6 by viboes, 8 years ago

Boost doesn't supports this combination. I think that it would be better to remove this checker and don't use C++11 with this library.

comment:7 by raad@…, 8 years ago

I see, thank you. I have to change to libc++ as soon as possible. But everything in Boost works except for this single compile error when variadic templates are switched on.

comment:8 by viboes, 8 years ago

I have assumed that if the compiler has variadic templates it has move semantic. In order to support the configuration you want I would need to make the distinction. Do you think it is worth the effort?

comment:9 by raad@…, 8 years ago

Well, there is a workaround (also disabling variadic templates when disabling rvalue references), so it's not critical.

But as the rest of Boost (including the rest of Boost.Thread) works in this configuration with variadic templates and without rvalue references and it seems that I'm not the only one using the latest clang with an older standard library, I think it's worth it if it's not too much work.

Maybe the simplest solution would be to disable the variadic version of call_once if BOOST_NO_CXX11_RVALUE_REFERENCES is defined? The attached patch works for me with all compiler and standard library combinations.

by raad@…, 8 years ago

Attachment: call_once_variadic.patch added

comment:10 by viboes, 8 years ago

Ok, I will do it.

comment:11 by viboes, 8 years ago

Milestone: To Be DeterminedBoost 1.56.0

comment:12 by raad@…, 8 years ago

I just saw that this is now in master. Thank you very much!

comment:13 by viboes, 8 years ago

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