Opened 13 years ago
Last modified 9 years ago
#4028 reopened Bugs
fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges
Reported by: | Mathias Gaunard | Owned by: | Joel de Guzman |
---|---|---|---|
Milestone: | To Be Determined | Component: | fusion |
Version: | Boost 1.42.0 | Severity: | Problem |
Keywords: | ADL range begin end | Cc: | mateusz@… |
Description
In C++0x, begin and end for ranges (that extract the beginning iterator and the past-the-end one, respectively) are to be found through ADL.
This causes problems when fusion is an associated namespace (as for example in the case iterator_range< some_iterator< fusion::vector<> > >
), since the begin and end of the fusion namespace will be considered by ADL, and that results in an error because a range is not a fusion sequence.
I see two (three) solutions:
- Mask fusion::begin and fusion::end with SFINAE so that they are only available if the argument is a fusion sequence. That means however that we can't have a fusion sequence that is at the same time a range, even though this could have some uses.
- Rename fusion::begin and fusion::end to something else.
(- Ask the standard people to reconsider)
Change History (11)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
I'm afraid I don't understand why this should be considered a GCC bug.
3.4.2 says:
If T is a template-id, its associated namespaces and classes are the namespace in which the template is defined; for member templates, the member template’s class; the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces in which any template template arguments are defined; and the classes in which any member templates used as template template arguments are defined. [Note: nontype template arguments do not contribute to the set of associated namespaces. ]
(emphasis added)
comment:3 by , 12 years ago
I'm not familiar with specification details or whether there has been a defect report regarding this. All I can say is that, IF we're talking about the same issue, 2 compilers besides GCC don't associate namespaces of template arguments. and that I have reported this as a bug to GCC. reply to my report: fixed in 4.5, not a regression.
here's a test case that triggers the bug (or non-bug) up to GCC 4.4:
namespace mpl{
class apply{}; class vector{};
}
template<class T> void apply(T const &){}
template<class T> class A{};
int main(){
A<mpl::vector> a; apply(a);
}
comment:4 by , 12 years ago
reconsidering, this seems like 2 different issues to me. I think GCC rightfully associates namespaces of template arguments. the bug here was that it didn't omit the type "apply" when it was looking for an ADL function.
as fusion::begin and std::begin are both functions this seems to be unrelated.
comment:5 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:6 by , 12 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
While a useful fix, note that still doesn't fix the underlying problem.
Here is a testcase that still fails:
#include <boost/array.hpp> #include <boost/fusion/container/vector.hpp> #include <boost/fusion/sequence/intrinsic/end.hpp> #include <boost/fusion/adapted/array.hpp> #include <boost/range.hpp> int main() { boost::array<boost::fusion::vector<>, 42> foo; begin(foo); // ambiguous, boost::begin or boost::fusion::begin }
Therefore I suggest the bug be left open.
comment:7 by , 12 years ago
Milestone: | Boost 1.43.0 → To Be Determined |
---|
What can we do?
I am not in favour of renaming fusion::begin/fusion::end - that would break a lot of code. We could remove the code to adapt arrays, or refactor it to a new facility that would adapt arrays by name (just like the named BOOST_FUSION_ADAPT_STRUCT_NAMED) - but this would break a lot of code as well. This does not solve the underlying problem of ambiguity either.
I suggest adding a note in the documentation that points out this issue and proposes to explicitly namespace-qualify calls to fusion::begin/fusion::end in generic user code.
comment:8 by , 12 years ago
I don't think we can do anything about that problem without breaking changes in Fusion.
Nevertheless the problem still exists in some cases, maybe it should be marked as partial wontfix ?
Forcing users to qualify begin and end doesn't solve the problem, since the C++0x for-loop construct calls those functions unqualified and relies on ADL. The real solution, to me, would be for the standard to reconsider the use of begin/end through ADL, but it's now too late for that.
comment:9 by , 12 years ago
I believe the only solution we have is to use an ADL barrier. E.g.
#include <boost/array.hpp> #include <boost/fusion/container/vector.hpp> #include <boost/fusion/sequence/intrinsic/end.hpp> #include <boost/fusion/adapted/array.hpp> #include <boost/range.hpp> namespace boost { namespace fusion { namespace adl_barrier { struct xx {}; } using ::boost::fusion::adl_barrier::xx; }} int main() { boost::array<boost::fusion::xx, 42> foo; begin(foo); }
comment:10 by , 9 years ago
Cc: | added |
---|
comment:11 by , 9 years ago
I have added basic adoption of std::array as Boost.Fusion sequence, #8241, and I'm interested in solving the ADL issue.
By the way, for easy reference, here is the old thread related to this issue: Fusion begin/end ADL issues with C++0x range-based for
I believe this is not a bug. not a boost bug anyway.
did you use GCC for this? up until GCC 4.4 it had a bug that caused ADL lookups in namespaces that are only referred to by template argument.
just because the "fusion" namespace appears in a template argument should not cause an ADL lookup in that namespace, if none of the arguments are in that namespace.
fixed in GCC 4.5 and other compilers.