Opened 9 years ago

Closed 9 years ago

#8668 closed Bugs (wontfix)

BOOST_FOREACH breaks on clang 3.2 but not on gcc 4.7.2

Reported by: juxeii@… Owned by: Eric Niebler
Milestone: To Be Determined Component: foreach
Version: Boost 1.52.0 Severity: Problem
Keywords: Cc:

Description

Consider this snippet:

#include <vector>
#include <boost/foreach.hpp>

class A : public std::vector<int>
{
public:
    template <class T>
    operator const T &() const;   
};

void foo(){
   A colA;
   int b = 1;
   BOOST_FOREACH(b, colA)
   {
        ;
   } 
}

clang 3.2 throws this error:

error: conditional expression is ambiguous; 'rvalue_probe<A>' can be converted to 'A' and vice versa BOOST_FOREACH(b, colA)

expanded from macro 'BOOST_FOREACH' f (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL))

expanded from macro 'BOOST_FOREACH_CONTAIN' BOOST_FOREACH_EVALUATE(COL)

expanded from macro 'BOOST_FOREACH_EVALUATE' (true ? boost::foreach_detail_::make_probe((COL), BOOST_FOREACH_ID(_foreach_is_rvalue)) : (COL))

gcc in version 4.7.2 compiles this snippet with no error. Is this a bug of gcc, clang or boost?

Change History (2)

comment:1 by viboes, 9 years ago

Component: Noneforeach
Owner: set to Eric Niebler

comment:2 by Eric Niebler, 9 years ago

Resolution: wontfix
Status: newclosed

It's not really a bug in gcc, clang, or boost. It's because in C++03, there's no perfect way to tell rvalues from lvalues. BOOST_FOREACH jumps through hoops of fire to figure it out, and it gets it right %100 of the time, +/- some epsilon. Congrats, you've found the epsilon. ;-)

If your container has an unconstrained conversion operator template, like A does above, it's not going to work. I think clang is right to reject it. The workaround is to compile with -std=gnu++11 or use C++11's range-based for loop. I'm afraid there's no way I know to make this work in C++03.

I encourage you to migrate to C++11. BOOST_FOREACH is legacy.

Note: See TracTickets for help on using tickets.