
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