Skip to content

Add CGAL_FOREACH#2634

Closed
sloriot wants to merge 16 commits intoCGAL:masterfrom
sloriot:CGAL-add_CGAL_FOREACH
Closed

Add CGAL_FOREACH#2634
sloriot wants to merge 16 commits intoCGAL:masterfrom
sloriot:CGAL-add_CGAL_FOREACH

Conversation

@sloriot
Copy link
Copy Markdown
Member

@sloriot sloriot commented Nov 27, 2017

Introduces CGAL_FOREACH that uses c++11 range loop for if available or BOOST_FOREACH.
There is a tiny variation as std::pair<T,T> is binded on the fly to Iterator_range<T>.

The files to be reviewed is STL_Extension/include/CGAL/foreach.h.

In passing 2bb0e40 and e34ca45 are bug-fixes not related to the change.

Fixes #2627
Replaces #2626

}

} }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mglisse Would you mind reviewing this file with the four overloads of CGAL::for_range_loop::make_range?

I am not sure but I think:

  1. The three overloads about std::pair could be replaced by one taking its parameter by copy.
  2. Maybe the fourth overload (generic) of make_range is not optimal.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The three overloads about std::pair could be replaced by one taking its parameter by copy.

Forgot to comment about this part but indeed, the last 2 std::pair overloads are redundant, the first one (const&) should suffice.


#define CGAL_FOREACH(A,B) for(A : CGAL::for_range_loop::make_range(B))
#else
#include <CGAL/foreach.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to include a boost header instead here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I did not exclude the header from sed input files

#else
/// \ingroup PkgStlExtension
/// If the version of `boost` is at least 1.51 and the compiler used support range-based for loops
/// introduced with \cpp11, use it; otherwise fallback onto `CGAL_FOREACH`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overeager sed again?

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Nov 28, 2017

The generic version is dangerous. If I have a function f that returns a vector (by value), CGAL_FOREACH(whatever,f()) will destruct the vector before even calling begin(). It would be safer to have T make_range(T&&) and T& make_range(T&), if you keep a make_range.

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Nov 28, 2017

Special handling for std::pair is a hack to delay the inevitable: stop using std::pair as a range. I can understand not being in a hurry to fix it though.

@lrineau
Copy link
Copy Markdown
Member

lrineau commented Nov 28, 2017

The generic version is dangerous. If I have a function f that returns a vector (by value), CGAL_FOREACH(whatever,f()) will destruct the vector before even calling begin(). It would be safer to have T make_range(T&&) and T& make_range(T&), if you keep a make_range.

What do you mean?

f() will be a temporary: a r-value of type vector<T>, so the generic make_range will be instantiated with vector<T>&&, and return a vector<T>&& as well. I do not see why you say the temporary will be destroyed before the call to begin(..).

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Nov 28, 2017

Try it on an example?
for(lhs:rhs) starts by doing auto&&range=rhs;. If rhs is a prvalue (a temporary object), range binds to it and extends its lifetime. If rhs is an xvalue (rvalue reference), range binds to the same object as the xvalue, but no lifetime extension occurs. The vector is destroyed. Next, for proceeds to initialize begin, end, and do the looping, on an object that is already dead.

@lrineau
Copy link
Copy Markdown
Member

lrineau commented Nov 29, 2017

Travis detected an error:

/home/travis/build/CGAL/cgal/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_spherical_removal.cpp:88:16: error: 
      unexpected type name 'Halfedge_handle': expected expression
  CGAL_FOREACH(Halfedge_handle hh, arr.halfedge_handles())
               ^
/home/travis/build/CGAL/cgal/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_spherical_removal.cpp:111:45: error: 
      expected '(' for function-style cast or type construction
    CGAL_FOREACH(Arrangement_2::Face_handle fh, arr.face_handles())
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~ ^

@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented Jan 3, 2018

@mglisse I think my last commit fixes the issue you mentioned. Do you see a better solution? (I cannot remove the extra overloads for std::pair as it does not pass the testsuite. I'll investigate).

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Jan 3, 2018

I think my last commit fixes the issue you mentioned.

Yes.

Do you see a better solution?

Stop using std::pair as ranges so we don't need the make_range helper at all? Stop supporting C++03?

(I cannot remove the extra overloads for std::pair as it does not pass the testsuite. I'll investigate).

You mean removing the & and && versions, keeping const&? I am curious what might cause it to fail...

@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented Jan 4, 2018

Here is the problematic call:

CGAL_FOREACH(Cell_handle& ch,
  std::make_pair(cells.begin(), cells.end()))

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Jan 4, 2018

Ah yes, of course, once you have a fully generic make_range overload, it is more specialized than the const pair& overload for a pair rvalue. We could use sfinae to disable the generic version for pairs, or dispatch some other way, but I guess what you have now is simpler. Let's just hope that nobody writes a function returning a const pair, or you'll need the extra const&& overload...

By the way, could we start replacing those std::make_pair with boost::make_iterator_range? These are the easy cases where the use of std::pair is not baked in the API.

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Jan 4, 2018

replace std::make_pair with CGAL::make_range in foreach loops

thanks 👍

@lrineau
Copy link
Copy Markdown
Member

lrineau commented Jan 4, 2018

conflicts

@sloriot sloriot force-pushed the CGAL-add_CGAL_FOREACH branch from 9dccf63 to 07c3835 Compare January 4, 2018 15:18
@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented Jan 4, 2018

Rebased

@lrineau lrineau added this to the 4.12-beta milestone Jan 4, 2018
@lrineau lrineau self-assigned this Jan 4, 2018
@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented Jan 5, 2018

There is the following error reported by travis with gcc 4.8.4.
I don't understand why it is ambiguous since get_chill() returns a lvalue reference.

/home/travis/build/CGAL/cgal/Classification/examples/Classification/../../include/CGAL/Classification/Sum_of_weighted_features_classifier.h: In member function ‘bool CGAL::Classification::Sum_of_weighted_features_classifier::load_configuration(std::istream&, bool)’:
/home/travis/build/CGAL/cgal/Classification/examples/Classification/../../include/CGAL/Classification/Sum_of_weighted_features_classifier.h:736:5: error: call of overloaded ‘make_range(boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >&)’ is ambiguous
     CGAL_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("classification.features"))
     ^
/home/travis/build/CGAL/cgal/Classification/examples/Classification/../../include/CGAL/Classification/Sum_of_weighted_features_classifier.h:736:5: note: candidates are:
/usr/local/include/CGAL/foreach.h:55:14: note: constexpr T& CGAL::for_range_loop::make_range(T&) [with T = boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >]
 constexpr T& make_range(T& t)
              ^
/usr/local/include/CGAL/foreach.h:61:13: note: constexpr T CGAL::for_range_loop::make_range(T&&) [with T = boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >&]
 constexpr T make_range(T&& t)
             ^

@mglisse
Copy link
Copy Markdown
Member

mglisse commented Jan 5, 2018

There is the following error reported by travis with gcc 4.8.4.

Looks like a bug in gcc-4.8, it compiles fine with 4.9.

@lrineau
Copy link
Copy Markdown
Member

lrineau commented Jan 8, 2018

Travis shows a compilation issue: https://travis-ci.org/CGAL/cgal/jobs/325369172#L1550

What is more, CGAL-4.12-Ic-134 seems rather red on older Windows, because of the lack of support of constexpr.

@lrineau
Copy link
Copy Markdown
Member

lrineau commented Jan 8, 2018

On my machine, /usr/include/boost/config/compiler/visualc.hpp contains:

// C++11 features supported by VC++ 14 update 3 (aka 2015)
//
#if (_MSC_FULL_VER < 190024210)
#  define BOOST_NO_CXX14_VARIABLE_TEMPLATES
#  define BOOST_NO_SFINAE_EXPR
#  define BOOST_NO_CXX11_CONSTEXPR
#endif

That means that constexpr was supported very late my MSVC: only in 2015 update 3. That explains why the code does not compile for versions of MSVC that know c++11 range-based for, but not constexpr.

@lrineau
Copy link
Copy Markdown
Member

lrineau commented May 16, 2018

Should this PR be removed?

@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented May 16, 2018

well the issue is still here but I need to look again to see how to fix the remaining issues.

@lrineau lrineau removed this from the 4.13-beta milestone Jun 26, 2018
@lrineau lrineau added this to the Trash / Attic milestone Jan 7, 2019
@sloriot sloriot closed this Mar 15, 2019
@sloriot
Copy link
Copy Markdown
Member Author

sloriot commented Mar 15, 2019

No longer needed with the move to C++14

@sloriot sloriot deleted the CGAL-add_CGAL_FOREACH branch May 3, 2019 06:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue with BOOST_FOREACH on Visual Studio 2015

4 participants