thread/call_once compile error on trunk on my code

Hello,
my svn and compiler versions are:
Path: .
URL: http://svn.boost.org/svn/boost/trunk
Repository Root: http://svn.boost.org/svn/boost
Repository UUID: b8fc166d-592f-0410-95f2-cb63ce0dd405
Revision: 83985
Node Kind: directory
Schedule: normal
Last Changed Author: viboes
Last Changed Rev: 83985
Last Changed Date: 2013-04-20 16:12:43 +0200 (Sat, 20 Apr 2013)
$ LANG=en g++ --version
g++ (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
and maybe the last changes
$ svn log boost/thread/pthread/once_atomic.hpp
------------------------------------------------------------------------
r83466 | viboes | 2013-03-16 16:36:21 +0100 (Sa, 16. Mär 2013) | 1 Zeile
Thread: add invoke when no variadic templates are available; adapt
call_once.
breaks my code now which is basically:
---8<---
namespace {
struct id_string
{
static boost::once_flag flag;
typedef std::map

Le 20/04/13 17:03, Olaf Peter a écrit :
Hello,
The error is about
/usr/local/include/boost/thread/detail/invoke.hpp: In function 'typename boost::enable_if_c<(! boost::is_member_function_pointer<Fp>::value), Ret>::type boost::detail::invoke(Fp&&, Args&& ...) [with Ret = void, Fp = void (*)({anonymous}::id_string&), Args = {{anonymous}::id_string}, typename boost::enable_if_c<(! boost::is_member_function_pointer<Fp>::value), Ret>::type = void]': /usr/local/include/boost/thread/pthread/once_atomic.hpp:127:9: instantiated from 'void boost::call_once(boost::once_flag&, Function&&, ArgTypes&& ...) [with Function = void (*)({anonymous}::id_string&), ArgTypes = {{anonymous}::id_string&}]' /home/olaf/work/token_ids.cpp:93:59: instantiated from here /usr/local/include/boost/thread/detail/invoke.hpp:406:65: error: invalid initialization of non-const reference of type '{anonymous}::id_string&' from an rvalue of type '{anonymous}::id_string'
Is this intentionally or do I miss something?
Hi, I see it breaks also code on msvc. I'm running the regression test on my computer with the attached patch. Could you tell me if it works for you? Best, Vicente

Le 20/04/13 18:17, Olaf Peter a écrit :
Is this intentionally or do I miss something?
Hi,
I see it breaks also code on msvc.
I'm running the regression test on my computer with the attached patch. Could you tell me if it works for you?
yes, it works. Committed revision 83988. Vicente

Le 20/04/13 17:03, Olaf Peter a écrit :
Hello,
g++ (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
and maybe the last changes ... breaks my code now which is basically:
namespace {
struct id_string { static boost::once_flag flag; typedef std::map
map_type; ... static void do_init(token_id_string& self) { insert(self.m_map)(x, "y")(...) ; }
std::string const& operator()(id::type id) const { boost::call_once(flag, &id_string::do_init, *this);
map_iterator s = m_map.find(id); ... } };
Hi,
the error
/usr/local/include/boost/thread/detail/invoke.hpp:406:65: error: invalid
initialization of non-const reference of type '{anonymous}::id_string&'
from an rvalue of type '{anonymous}::id_string'
says you that the parameter (const) can not be used where a non-const is
expected.
Shouldn't the operator be declared non-const
std::string const& operator()(id::type id) ;
In addition if you want to pass a reference you would need to use
boost::ref().
The following compile well without the patch
struct id_string
{
static boost::once_flag flag;
static void do_init(id_string & )
{}
void operator()()
{
boost::call_once(flag, &id_string::do_init, boost::ref(*this));
}
};
Note that the following compiles
struct id_string
{
static boost::once_flag flag;
static void do_init(id_string & )
{}
void operator()()
{
std::bind(&id_string::do_init, std::ref(*this))();
}
void operator()(int) const
{
std::bind(&id_string::do_init, *this)();
}
};
I would expect that the preceding fails as *this is a 'id_string const&'
and do_init expects an 'id_string &'.
This would explain why with the patch it worked as the patch was calling
to std::bind.
But if make use of the class
{
id_string id;
//id();
id(1);
}
I get the following error
gcc.compile.c++
/tmp/bin.v2/boost/bin.v2/libs/thread/test/call_once_p.test/gcc-4.6.1.0x/debug/threading-multi/sync/mutual_exclusion/once/call_once/call_once_pass.o
In file included from /usr/include/c++/4.6/functional:56:0,
from ../../../boost/thread/detail/invoke.hpp:34,
from ../../../boost/thread/pthread/once_atomic.hpp:17,
from ../../../boost/thread/once.hpp:20,
from sync/mutual_exclusion/once/call_once/call_once_pass.cpp:26:
/usr/include/c++/4.6/tuple: In constructor ‘constexpr
std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with
unsigned int _Idx = 0u, _Head = id_string]’:
/usr/include/c++/4.6/tuple:162:44: instantiated from ‘constexpr
std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&,
const _Tail& ...) [with unsigned int _Idx = 0u, _Head = id_string, _Tail
= {}]’
/usr/include/c++/4.6/tuple:423:24: instantiated from ‘constexpr
std::tuple<_T1>::tuple(const _T1&) [with _T1 = id_string]’
/usr/include/c++/4.6/functional:1186:70: instantiated from
‘std::_Bind<_Functor(_Bound_args ...)>::_Bind(_Functor&&, _Args&& ...)
[with _Args = {const id_string&}, _Functor = void (*)(id_string&),
_Bound_args = {id_string}]’
/usr/include/c++/4.6/functional:1450:41: instantiated from ‘typename
std::_Bind_helper<_Functor, _ArgTypes>::type std::bind(_Functor&&,
_ArgTypes&& ...) [with _Functor = void (*)(id_string&), _ArgTypes =
{const id_string&}, typename std::_Bind_helper<_Functor,
_ArgTypes>::type = std::_Bind

namespace {
struct id_string { static boost::once_flag flag; typedef std::map
map_type; ... static void do_init(token_id_string& self) {
Mmh, wrong reduced/generalized even if I checked carefully, should be static void do_init(id_string& self) { insert(/* aka *this */self.m_map)(x, "y")(...) } But I see, you recognized this.
insert(self.m_map)(x, "y")(...) ; }
std::string const& operator()(id::type id) const { boost::call_once(flag, &id_string::do_init, *this);
map_iterator s = m_map.find(id); ... } };
Hi,
the error /usr/local/include/boost/thread/detail/invoke.hpp:406:65: error: invalid initialization of non-const reference of type '{anonymous}::id_string&' from an rvalue of type '{anonymous}::id_string'
says you that the parameter (const) can not be used where a non-const is expected.
Shouldn't the operator be declared non-const
std::string const& operator()(id::type id) ;
The idea was to create a lazy lookup since this functor is only used on debugging, but compiled/linked at all build targets (I know, project structure ...). Imo making the member const/non-const is a taste of matter; const since it does primary a lookup, non-const due to the lazy initialization. So, I'm not sure.
In addition if you want to pass a reference you would need to use boost::ref().
The following compile well without the patch
struct id_string { static boost::once_flag flag; static void do_init(id_string & ) {} void operator()() { boost::call_once(flag, &id_string::do_init, boost::ref(*this)); } };
Note that the following compiles
struct id_string { static boost::once_flag flag; static void do_init(id_string & ) {} void operator()() { std::bind(&id_string::do_init, std::ref(*this))(); } void operator()(int) const { std::bind(&id_string::do_init, *this)(); } };
I would expect that the preceding fails as *this is a 'id_string const&' and do_init expects an 'id_string &'. This would explain why with the patch it worked as the patch was calling to std::bind.
But if make use of the class
{ id_string id; //id(); id(1); }
I get the following error
gcc.compile.c++ /tmp/bin.v2/boost/bin.v2/libs/thread/test/call_once_p.test/gcc-4.6.1.0x/debug/threading-multi/sync/mutual_exclusion/once/call_once/call_once_pass.o
In file included from /usr/include/c++/4.6/functional:56:0, from ../../../boost/thread/detail/invoke.hpp:34, from ../../../boost/thread/pthread/once_atomic.hpp:17, from ../../../boost/thread/once.hpp:20, from sync/mutual_exclusion/once/call_once/call_once_pass.cpp:26: /usr/include/c++/4.6/tuple: In constructor ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with unsigned int _Idx = 0u, _Head = id_string]’: /usr/include/c++/4.6/tuple:162:44: instantiated from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with unsigned int _Idx = 0u, _Head = id_string, _Tail = {}]’ /usr/include/c++/4.6/tuple:423:24: instantiated from ‘constexpr std::tuple<_T1>::tuple(const _T1&) [with _T1 = id_string]’ /usr/include/c++/4.6/functional:1186:70: instantiated from ‘std::_Bind<_Functor(_Bound_args ...)>::_Bind(_Functor&&, _Args&& ...) [with _Args = {const id_string&}, _Functor = void (*)(id_string&), _Bound_args = {id_string}]’ /usr/include/c++/4.6/functional:1450:41: instantiated from ‘typename std::_Bind_helper<_Functor, _ArgTypes>::type std::bind(_Functor&&, _ArgTypes&& ...) [with _Functor = void (*)(id_string&), _ArgTypes = {const id_string&}, typename std::_Bind_helper<_Functor, _ArgTypes>::type = std::_Bind
]’ sync/mutual_exclusion/once/call_once/call_once_pass.cpp:206:43: instantiated from here /usr/include/c++/4.6/tuple:97:25: erreur: use of deleted function ‘id_string::id_string(const id_string&)’ sync/mutual_exclusion/once/call_once/call_once_pass.cpp:194:8: erreur: ‘id_string::id_string(const id_string&)’ is implicitly deleted because the default definition would be ill-formed: sync/mutual_exclusion/once/call_once/call_once_pass.cpp:194:8: erreur: use of deleted function ‘boost::once_flag::once_flag(const boost::once_flag&)’ ../../../boost/thread/pthread/once_atomic.hpp:59:5: erreur: declared here Could you tell me if works for you after rolling back the patch and adding the suggested changes on your code?
you mean using boost::ref? I'm not sure if I have std::ref on my old gcc compiler 4.6.3. Anyway, with thread/detail/invoke.hpp from Revision: 83985 std::string const& operator()(id::type id) { boost::call_once(flag, &id_string::do_init, boost::ref(*this)); map_iterator s = m_map.find(id); if (s == m_map.end()) { return m_map[id::invalid]; } else { return s->second; } ... } compiles, but not std::string const& operator()(id::type id) const, neither with ref or cref. Thanks, Olaf

Le 21/04/13 19:46, Olaf Peter a écrit :
Hi,
the error /usr/local/include/boost/thread/detail/invoke.hpp:406:65: error: invalid initialization of non-const reference of type '{anonymous}::id_string&' from an rvalue of type '{anonymous}::id_string'
says you that the parameter (const) can not be used where a non-const is expected.
Shouldn't the operator be declared non-const
std::string const& operator()(id::type id) ;
The idea was to create a lazy lookup since this functor is only used on debugging, but compiled/linked at all build targets (I know, project structure ...). Imo making the member const/non-const is a taste of matter; const since it does primary a lookup, non-const due to the lazy initialization. So, I'm not sure. I don't think the compiler lets you choose. If do_init expect a non const, you must pass a non-const.
In addition if you want to pass a reference you would need to use boost::ref().
The following compile well without the patch
struct id_string { static boost::once_flag flag; static void do_init(id_string & ) {} void operator()() { boost::call_once(flag, &id_string::do_init, boost::ref(*this)); } };
Note that the following compiles
struct id_string { static boost::once_flag flag; static void do_init(id_string & ) {} void operator()() { std::bind(&id_string::do_init, std::ref(*this))(); } void operator()(int) const { std::bind(&id_string::do_init, *this)(); } };
I would expect that the preceding fails as *this is a 'id_string const&' and do_init expects an 'id_string &'. This would explain why with the patch it worked as the patch was calling to std::bind.
you mean using boost::ref? I'm not sure if I have std::ref on my old gcc compiler 4.6.3. Anyway, with thread/detail/invoke.hpp from Revision: 83985
std::string const& operator()(id::type id) { boost::call_once(flag, &id_string::do_init, boost::ref(*this));
map_iterator s = m_map.find(id);
if (s == m_map.end()) { return m_map[id::invalid]; } else { return s->second; } ... }
compiles, Great. but not std::string const& operator()(id::type id) const, neither with ref or cref.
As I said it is normal that compilation fails in this case. *this is 'id_string const&' and do init expects 'id_string &' Best, Vicente
participants (2)
-
Olaf Peter
-
Vicente J. Botet Escriba