boost::range RangeConcept problem.

The following snippet is the mock-up of the problem I am having in order to be able to reproduce. -------------------------------------------------------------------------------- #include <iostream> #include <boost/range.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <boost/bind.hpp> #include <boost/assign.hpp> using namespace boost::assign; struct wxSize { wxSize(int height=0,int width=0):m_height(height),m_width(width) { } int GetWidth() const {return m_width;} int m_height; int m_width; }; class wxWindowBase { public: wxSize GetTextExtent(const std::string val) { return wxSize(0,val.length()); } void DoLayout(std::vector<std::string> m_FilteredItems) { using boost::adaptors::transformed; wxSize longest = *boost::max_element(m_FilteredItems | transformed(boost::bind(&wxWindowBase::GetTextExtent,this,_1)), boost::bind(std::less<int>(),boost::bind(&wxSize::GetWidth,_1),boost::bind(&wxSize::GetWidth,_2))); std::cout <<longest.GetWidth(); } }; int main() { std::vector<std::string> input; input += "o","two","threexxx","four"; wxWindowBase window; window.DoLayout(input); } ----------------------------------------------------------------------------------------- The above code fails to compile on GCC4.7.2 and MSVC10 although it compiles and runs fine on clang3.3
From what I understand ,transformed returns a Single Pass Range and max_element expects a ForwardRange and that's the gist of the problem.But it works for something like
max_element(someint_vector | transformed(doubleit()),std::less<int>()); without problems. Is there a elegant way to achieve what I am trying to without using a intermediate container? Thanks in advance..

Hi Hurcan, 2013/1/16 Hurcan Solter <hsolter@gmail.com>
The following snippet is the mock-up of the problem I am having in order to be able to reproduce.
-------------------------------------------------------------------------------- #include <iostream> #include <boost/range.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <boost/bind.hpp> #include <boost/assign.hpp>
using namespace boost::assign; struct wxSize { wxSize(int height=0,int width=0):m_height(height),m_width(width) { } int GetWidth() const {return m_width;} int m_height; int m_width; }; class wxWindowBase { public: wxSize GetTextExtent(const std::string val) { return wxSize(0,val.length()); } void DoLayout(std::vector<std::string> m_FilteredItems) {
using boost::adaptors::transformed; wxSize longest = *boost::max_element(m_FilteredItems | transformed(boost::bind(&wxWindowBase::GetTextExtent,this,_1)),
boost::bind(std::less<int>(),boost::bind(&wxSize::GetWidth,_1),boost::bind(&wxSize::GetWidth,_2)));
std::cout <<longest.GetWidth(); } }; int main() { std::vector<std::string> input; input += "o","two","threexxx","four"; wxWindowBase window; window.DoLayout(input); }
----------------------------------------------------------------------------------------- The above code fails to compile on GCC4.7.2 and MSVC10 although it compiles and runs fine on clang3.3
From what I understand ,transformed returns a Single Pass Range and max_element expects a ForwardRange and that's the gist of the problem.But it works for something like
max_element(someint_vector | transformed(doubleit()),std::less<int>()); without problems.
Is there a elegant way to achieve what I am trying to without using a intermediate container? Thanks in advance..
This problem's some solution: 1. Don't use member function version `bind` in `transformed`. the `bind`'s result functor is not DefaultConstructible. An iterator holding such a functor can't conform to even Input Iterator. (`max_element` need default construct operation for iterator.) 2. Use `regular` function. `regular` function is Boost.Range extension library's feature. `regular` function is convert functor to DefaultConstructible and CopyAssignable. http://dl.dropbox.com/u/1682460/git/OvenToBoost/libs/range/doc/html/range_ex... http://dl.dropbox.com/u/1682460/git/OvenToBoost/libs/range/doc/html/range_ex... #include <boost/range/adaptor/regular_extension/transformed.hpp> wxSize longest = *boost::max_element(m_FilteredItems |+ transformed(boost::bind(&wxWindowBase::GetTextExtent,this,_1)), boost::bind(std::less<int>(),boost::bind(&wxSize::GetWidth,_1),boost::bind(&wxSize::GetWidth,_2))); You can get here: https://github.com/faithandbrave/OvenToBoost This extension is now reviewing by Boost.Range developers. Thanks, Akira
======================== Akira Takahashi mailto:faithandbrave@gmail.com https://sites.google.com/site/faithandbrave/about/en

On Tue, Jan 15, 2013 at 10:26 AM, Hurcan Solter <hsolter@gmail.com> wrote:
The following snippet is the mock-up of the problem I am having in order to be able to reproduce.
-------------------------------------------------------------------------------- #include <iostream> #include <boost/range.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <boost/bind.hpp> #include <boost/assign.hpp>
using namespace boost::assign; struct wxSize { wxSize(int height=0,int width=0):m_height(height),m_width(width) { } int GetWidth() const {return m_width;} int m_height; int m_width; }; class wxWindowBase { public: wxSize GetTextExtent(const std::string val) { return wxSize(0,val.length()); } void DoLayout(std::vector<std::string> m_FilteredItems) {
using boost::adaptors::transformed; wxSize longest = *boost::max_element(m_FilteredItems | transformed(boost::bind(&wxWindowBase::GetTextExtent,this,_1)),
boost::bind(std::less<int>(),boost::bind(&wxSize::GetWidth,_1),boost::bind(&wxSize::GetWidth,_2)));
std::cout <<longest.GetWidth(); } }; int main() { std::vector<std::string> input; input += "o","two","threexxx","four"; wxWindowBase window; window.DoLayout(input); }
----------------------------------------------------------------------------------------- The above code fails to compile on GCC4.7.2 and MSVC10 although it compiles and runs fine on clang3.3
From what I understand ,transformed returns a Single Pass Range and max_element expects a ForwardRange and that's the gist of the problem.But it works for something like
max_element(someint_vector | transformed(doubleit()),std::less<int>()); without problems.
Is there a elegant way to achieve what I am trying to without using a intermediate container? Thanks in advance..
I would try simplifying things (e.g., replace the uses of bind with explicit function objects; define an operator< for wxSize), then if you're still lost, paste the error (I don't have immediate access to MSVC 10 or gcc 4.7). - Jeff

On Thu, Jan 17, 2013 at 5:25 AM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Tue, Jan 15, 2013 at 10:26 AM, Hurcan Solter <hsolter@gmail.com> wrote:
The following snippet is the mock-up of the problem I am having in order to be able to reproduce.
-------------------------------------------------------------------------------- #include <iostream> #include <boost/range.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <boost/bind.hpp> #include <boost/assign.hpp>
using namespace boost::assign; struct wxSize { wxSize(int height=0,int width=0):m_height(height),m_width(width) { } int GetWidth() const {return m_width;} int m_height; int m_width; }; class wxWindowBase { public: wxSize GetTextExtent(const std::string val) { return wxSize(0,val.length()); } void DoLayout(std::vector<std::string> m_FilteredItems) {
using boost::adaptors::transformed; wxSize longest = *boost::max_element(m_FilteredItems | transformed(boost::bind(&wxWindowBase::GetTextExtent,this,_1)),
boost::bind(std::less<int>(),boost::bind(&wxSize::GetWidth,_1),boost::bind(&wxSize::GetWidth,_2)));
std::cout <<longest.GetWidth(); } }; int main() { std::vector<std::string> input; input += "o","two","threexxx","four"; wxWindowBase window; window.DoLayout(input); }
----------------------------------------------------------------------------------------- The above code fails to compile on GCC4.7.2 and MSVC10 although it compiles and runs fine on clang3.3
From what I understand ,transformed returns a Single Pass Range and max_element expects a ForwardRange and that's the gist of the problem.But it works for something like
max_element(someint_vector | transformed(doubleit()),std::less<int>()); without problems.
Is there a elegant way to achieve what I am trying to without using a intermediate container? Thanks in advance..
I would try simplifying things (e.g., replace the uses of bind with explicit function objects; define an operator< for wxSize), then if you're still lost, paste the error (I don't have immediate access to MSVC 10 or gcc 4.7).
- Jeff
I am pretty convinced that Akira has nailed it. The problem was in the first line and in any case it does not make sense defining operator < for size objects unless you are comparing areas and as for functors I've used bind exclusively to avoid writing them (hence the std::less) .
Seeing that it compiles fine on clang I've disabled concept checks by defining BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 . Apparently clang bypasses concept check or maybe it's disabled for that particular compiler (Is it?) . It works fine on both MSVC and gcc now. Although I might be shooting myself in the foot
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Akira Takahashi
-
Hurcan Solter
-
Jeffrey Lee Hellrung, Jr.