#1295 closed Feature Requests (wontfix)
for each in VC8+
Reported by: | NN | Owned by: | Eric Niebler |
---|---|---|---|
Milestone: | To Be Determined | Component: | foreach |
Version: | Boost 1.34.1 | Severity: | Optimization |
Keywords: | Cc: |
Description
VC8 and VC9 have built in for each operator. BOOST_FOREACH should use it instead. This can decrease compilation time.
Code sample:
#if defined(_MSC_VER) && _MSC_VER >= 1400 #define BOOST_FOREACH(i, c) for each(i in c) #else // BOOST_FOREACH #endif // _MSC_VER && _MSC_VER >= 1400
Change History (7)
comment:1 by , 15 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
comment:2 by , 15 years ago
VC can iterate over native array and iterator ranges. In VC9 you can iterate over string literals too.
There is no option to change variables, but this can be easily fixed with const_cast.
This what you can do with VC9 for each:
#include <boost/array.hpp> #include <boost/range/iterator_range.hpp> #include <vector> template<typename T, size_t N> boost::array<T, N> make_array_range() { boost::array<T, N> a; T c = 0; for each(T const& i in a) const_cast<T&>(i) = c++; return a; } int main() { for each(int i in make_array_range<int, 10>()) printf("%d", i); typedef boost::array<int, 10> ints; ints a = make_array_range<int, 10>(); boost::iterator_range<ints::iterator> x(a.begin(), a.end()); for each(ints::const_reference i in x) printf("%d", i); for each(char% c in "asdf") printf("%c", c); typedef std::vector<int> vints; vints v(a.begin(), a.end()); for each(vints::const_reference i in v) const_cast<vints::reference>(i) = 0; }
Of course this is not full replacement of Boost.Foreach.
comment:3 by , 15 years ago
Resolution: | wontfix |
---|---|
Status: | closed → reopened |
I have found the way to make it work with all requirements:
#include <boost/range/iterator_range.hpp> #include <boost/foreach.hpp> #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC 8.0+ #define foreach(var, col) \ for each(var in (::boost::make_iterator_range(col))) #else // Other compilers #define foreach BOOST_FOREACH #endif // defined(_MSC_VER) && _MSC_VER >= 1400 // VC 8.0+
There is a code for test:
#include <boost/range/begin.hpp> #include <boost/range/end.hpp> #include <boost/array.hpp> #include <boost/lambda/lambda.hpp> #include <vector> #include <cassert> #include <iostream> #include <iterator> namespace my { // Extensibility check struct non_iteratable { non_iteratable() { x[0] = 0; x[1] = 1; } typedef boost::array<int, 2> x_type; x_type x; }; non_iteratable::x_type::iterator boost_range_begin(non_iteratable& c) { return boost::begin(c.x); } non_iteratable::x_type::iterator boost_range_end(non_iteratable& c) { return boost::end(c.x); } non_iteratable::x_type::const_iterator boost_range_begin(non_iteratable const& c) { return boost::begin(c.x); } non_iteratable::x_type::const_iterator boost_range_end(non_iteratable const& c) { return boost::end(c.x); } } // namespace my namespace boost { // specialize rannge_iterator and range_const_iterator in namespace boost template<> struct range_iterator<my::non_iteratable> { typedef my::non_iteratable::x_type::iterator type; }; template<> struct range_const_iterator<my::non_iteratable> { typedef my::non_iteratable::x_type::const_iterator type; }; } // namespace boost int main() { { // Regular array int a[10] = {}; // Value foreach(int i, a) std::cout << i; // Reference to const foreach(int const& i, a) std::cout << i; // Reference to non Const foreach(int& i, a) i = 1; assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a)); } { // Boost.Array boost::array<int, 10> a = {}; // Value foreach(int i, a) std::cout << i; // Reference to const foreach(int const& i, a) std::cout << i; // Reference to non Const foreach(int& i, a) i = 1; assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a)); } { // Std.Vector std::vector<int> a(10); // Value foreach(int i, a) std::cout << i; // Reference to const foreach(int const& i, a) std::cout << i; // Reference to non Const foreach(int& i, a) i = 1; assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a)); } // Extensibility { my::non_iteratable a; // Value foreach(int i, a) std::cout << i; // Reference to const foreach(int const& i, a) std::cout << i; // Reference to non Const foreach(int& i, a) i = 1; assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a)); } }
The code works as expected. Thank you for attention.
comment:4 by , 15 years ago
Resolution: | → wontfix |
---|---|
Status: | reopened → closed |
Sorry, no. If you try replacing the BOOST_FOREACH macro as you suggest and run the foreach regression tests, you'll see that this does not handle rvalue collections correctly. Besides, BOOST_FOREACH has well-defined customization hooks, which this implementation is not respecting. There is simply no way.
comment:6 by , 15 years ago
Here: http://rsdn.ru/forum/message/2907464.1.aspx I have some for each implementation. It does not passes rvalue.
But the code is more optimized than BOOST_FOREACH.
Can't be done. MSVC 'for each' can't operate on native array types, iterator ranges or C strings nor is extensible via Boost.Range customization points. 'for each' also cannot iterate over an STL container using a non-const reference iteration variable.
Nobody has complained about compile times with BOOST_FOREACH.