reference to ‘_1’ is ambiguous
Hi, This problem has appeared before on the list but in a different context. The following code std::vector<int> myvec; for_each(myvec, std::cout<<_1<<' '); gives the error: Serializer.h:78: error: reference to ‘_1’ is ambiguous /home/sandeep/Computing/boost_1_38_0/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /home/sandeep/Computing/boost_1_38_0/boost/bind/placeholders.hpp:54: error: boost::arg<1> <unnamed>::_1 Serializer.h:78: error: reference to ‘_1’ is ambiguous I believe boost/bind is getting included indirectly via some other library. I have tried several modification but none seem to work as I was quite reluctant to post a third mail on the list. Thanks, sandep
AMDG Sandeep Gupta wrote:
This problem has appeared before on the list but in a different context. The following code
std::vector<int> myvec; for_each(myvec, std::cout<<_1<<' ');
gives the error:
Serializer.h:78: error: reference to ‘_1’ is ambiguous /home/sandeep/Computing/boost_1_38_0/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /home/sandeep/Computing/boost_1_38_0/boost/bind/placeholders.hpp:54: error: boost::arg<1> <unnamed>::_1 Serializer.h:78: error: reference to ‘_1’ is ambiguous
I believe boost/bind is getting included indirectly via some other library. I have tried several modification but none seem to work as I was quite reluctant to post a third mail on the list.
qualify _1, either with boost::lambda:: or with some namespace alias. In Christ, Steven Watanabe
On Tue, Mar 17, 2009 at 8:50 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Sandeep Gupta wrote:
This problem has appeared before on the list but in a different context. The following code
std::vector<int> myvec; for_each(myvec, std::cout<<_1<<' ');
gives the error:
Serializer.h:78: error: reference to ‘_1’ is ambiguous /home/sandeep/Computing/boost_1_38_0/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /home/sandeep/Computing/boost_1_38_0/boost/bind/placeholders.hpp:54: error: boost::arg<1> <unnamed>::_1 Serializer.h:78: error: reference to ‘_1’ is ambiguous
I believe boost/bind is getting included indirectly via some other library. I have tried several modification but none seem to work as I was quite reluctant to post a third mail on the list.
qualify _1, either with boost::lambda:: or with some namespace alias.
Thanks so much Steve. This was rather simple oversight. My mistake. -Sandeep
Sandeep Gupta wrote:
On Tue, Mar 17, 2009 at 8:50 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Sandeep Gupta wrote:
Serializer.h:78: error: reference to ‘_1’ is ambiguous
qualify _1, either with boost::lambda:: or with some namespace alias.
Thanks so much Steve. This was rather simple oversight. My mistake.
Would be nice if bind() didn't cause this. Are the placeholders going to be in an anonymous namespace when added to the std lib?
Noah Roberts:
Would be nice if bind() didn't cause this.
I can probably get the placeholders out of the global namespace in 1.41.
Are the placeholders going to be in an anonymous namespace when added to the std lib?
No, they're in namespace std::placeholders.
Nat Goodspeed:
Peter Dimov wrote:
I can probably get the placeholders out of the global namespace in 1.41.
I saw a suggestion a while ago to share the *same* placeholders for boost::bind, boost::lambda, Phoenix et al. I'm hoping that's where we're headed?
Lambda only goes to _3 and it's not easy to remove this limit. I doubt that anyone would invest the effort.
Peter Dimov wrote:
Noah Roberts:
Would be nice if bind() didn't cause this.
I can probably get the placeholders out of the global namespace in 1.41.
Are the placeholders going to be in an anonymous namespace when added to the std lib?
No, they're in namespace std::placeholders.
You, Joel de Guzman, Dan Marsden and I should coordinate. We might be able to use Proto so that the bind placeholders can be shared with the Phoenix placeholders, eliminating this source of confusion once and for all. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler:
Peter Dimov wrote:
Noah Roberts:
Would be nice if bind() didn't cause this.
I can probably get the placeholders out of the global namespace in 1.41.
Are the placeholders going to be in an anonymous namespace when added to the std lib?
No, they're in namespace std::placeholders.
You, Joel de Guzman, Dan Marsden and I should coordinate. We might be able to use Proto so that the bind placeholders can be shared with the Phoenix placeholders, eliminating this source of confusion once and for all.
Bind can already use any placeholders (and in fact does recognize the Lambda placeholders). No coordination is needed, just a specialization of boost::is_placeholder. The main problem is that all code that relies on the placeholders being visible will break. A secondary problem I have is that to keep Bind header-only I (think I) need to move to using inline functions instead of objects for _K on all compilers. This will consume one release cycle, during which the global placeholders will be "deprecated". The next release will remove them from the global namespace. But if there's a Boost-wide header that defines _K, I can easily make Bind use it.
Peter Dimov wrote:
Eric Niebler:
You, Joel de Guzman, Dan Marsden and I should coordinate. We might be able to use Proto so that the bind placeholders can be shared with the Phoenix placeholders, eliminating this source of confusion once and for all.
Bind can already use any placeholders (and in fact does recognize the Lambda placeholders). No coordination is needed, just a specialization of boost::is_placeholder.
The main problem is that all code that relies on the placeholders being visible will break.
You mean code that requires the placeholders to be at global scope? Why not bring them into the global scope with a using declaration?
A secondary problem I have is that to keep Bind header-only I (think I) need to move to using inline functions instead of objects for _K on all compilers. This will consume one release cycle, during which the global placeholders will be "deprecated". The next release will remove them from the global namespace.
You are talking about ODR violations in code that refers to const objects at namespace scope? There are ways around this problem.... namespace boost { namespace placeholders { template<class I> struct placeholder_instance { placeholder<I> const value; }; // statically initialized ... template<class I> placeholder<I> const placeholder_instance<I>::value = {{}}; namespace { // This reference should also be statically initialized placeholder<mpl::int_<1> > const & _1 = placeholder_instance<mpl::int_<1> >::value; } }} // for back-compatibility ... using boost::placeholders::_1; Now every use of _1 refers to the same object, even across translation units, and it's all header-only. Not all compilers support this yet, but Dave and I fought to get this approved for C++0x. For older compilers, I think we can live with the ODR, as these objects will be stateless (identity doesn't matter). If placeholder<> is an appropriately-defined Proto terminal, then it can be reused in Phoenix.
But if there's a Boost-wide header that defines _K, I can easily make Bind use it.
I think it should all be possible. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler: ...
namespace { // This reference should also be statically initialized placeholder<mpl::int_<1> > const & _1 = placeholder_instance<mpl::int_<1> >::value; }
This is a problem for some precompiled header implementations. Some compilers have fixed theirs to allow it, some have not, some only allow(ed?) it when the variables are static. Our tests don't show the problem since they don't use precompiled headers. So we've relied on bug reports to iron these out, leading to the current status quo in boost/bind/placeholders.hpp. Using inline functions: static inline boost::arg<1> _1() { return boost::arg<1>(); } is the most conservative option since it works everywhere, but it does have the disadvantage that one cannot overload operators for _1.
Peter Dimov wrote:
Eric Niebler: ...
namespace { // This reference should also be statically initialized placeholder<mpl::int_<1> > const & _1 = placeholder_instance<mpl::int_<1> >::value; }
This is a problem for some precompiled header implementations.
Huh.
Some compilers have fixed theirs to allow it, some have not, some only allow(ed?) it when the variables are static.
I notice I left "static" out of the example I sent around, but yes, placeholder_instance<>::value is supposed to be a class static.
Our tests don't show the problem since they don't use precompiled headers.
Step 1: add tests that exhibit the problem with precompiled headers.
So we've relied on bug reports to iron these out, leading to the current status quo in boost/bind/placeholders.hpp.
Using inline functions:
static inline boost::arg<1> _1() { return boost::arg<1>(); }
is the most conservative option since it works everywhere, but it does have the disadvantage that one cannot overload operators for _1.
And bind is one of those libraries that we want to work even on ancient compilers.... <sigh> Maybe we can have a separate Boost.Bind v2 library, like we now have signals and signals2. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler:
Peter Dimov wrote:
Eric Niebler: ...
namespace { // This reference should also be statically initialized placeholder<mpl::int_<1> > const & _1 = placeholder_instance<mpl::int_<1> >::value; }
This is a problem for some precompiled header implementations.
Huh.
Yep. Apparently, the unnamed namespace does not get an unique name in every translation unit because of the precompilation.
Some compilers have fixed theirs to allow it, some have not, some only allow(ed?) it when the variables are static.
I notice I left "static" out of the example I sent around, but yes, placeholder_instance<>::value is supposed to be a class static.
This is not what I meant. On some compilers (going by the #ifdefs, MSVC and Metrowerks), this: namespace { X x; } doesn't work in a precompiled header, but this: namespace { static X x; } does (because a static x doesn't cause a multiple definition link error.) On Borland, neither works in a PCH. On g++ 4, both work but the second causes an "unused variable" warning for every _K that is not referenced, which is a bit annoying. I'm not sure what works on g++ 3, but it uses the inline function path. :-)
Sandeep Gupta wrote:
Hi, This problem has appeared before on the list but in a different context. The following code
std::vector<int> myvec; for_each(myvec, std::cout<<_1<<' ');
gives the error:
Serializer.h:78: error: reference to ‘_1’ is ambiguous /home/sandeep/Computing/boost_1_38_0/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /home/sandeep/Computing/boost_1_38_0/boost/bind/placeholders.hpp:54: error: boost::arg<1> <unnamed>::_1 Serializer.h:78: error: reference to ‘_1’ is ambiguous
I believe boost/bind is getting included indirectly via some other library. I have tried several modification but none seem to work as I was quite reluctant to post a third mail on the list.
Disregaring the bind inclusion part, what about: for_each(myvec, std::cout << ::boost::lambda::_1 << ' '); / Johan
Johan Nilsson wrote:
Sandeep Gupta wrote:
Hi, This problem has appeared before on the list but in a different context. The following code
std::vector<int> myvec; for_each(myvec, std::cout<<_1<<' ');
gives the error:
Serializer.h:78: error: reference to ‘_1’ is ambiguous /home/sandeep/Computing/boost_1_38_0/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /home/sandeep/Computing/boost_1_38_0/boost/bind/placeholders.hpp:54: error: boost::arg<1> <unnamed>::_1 Serializer.h:78: error: reference to ‘_1’ is ambiguous
I believe boost/bind is getting included indirectly via some other library. I have tried several modification but none seem to work as I was quite reluctant to post a third mail on the list.
Disregaring the bind inclusion part, what about:
for_each(myvec, std::cout << ::boost::lambda::_1 << ' ');
/ Johan
This has come up before for me, and I've always solved it in a similar way.
participants (8)
-
Eric Niebler
-
Johan Nilsson
-
Kenny Riddile
-
Nat Goodspeed
-
Noah Roberts
-
Peter Dimov
-
Sandeep Gupta
-
Steven Watanabe