Another generic program that won't compile with pointee, bind, and array

Here's another (simplified) program I can't get to work. I'm trying to write a generic routine that finds the largest element of a sequence. It is assumed that element->size() is defined, as it is for boost::array and std::string. For some reason, the Largest template function works okay for std::strings, but not for boost::arrays. Can you tell me what is wrong? Will you please offer some improvements for error detection and debugging techniques that would have helped here? Perhaps I need a "typename" or "template" somewhere. Take it as given that I have a String class that needs to be a fixed-size array. Here's the code: #include <boost/operators.hpp> #include <boost/static_assert.hpp> #include <boost/function.hpp> #include <boost/tuple/tuple.hpp> #include <boost/iterator/iterator_traits.hpp> #include <boost/bind.hpp> #include <boost/array.hpp> #include <boost/pointee.hpp> #include <cstddef> #include <iterator> #include <algorithm> #include <functional> #include <string> #include <vector> #include <iostream> #include <iomanip> template <class InIter> InIter Largest(InIter first, InIter last) { typedef typename boost::pointee<InIter>::type ObjType; InIter largest = std::max_element(first, last, boost::bind(std::less<std::size_t>(), boost::bind(&ObjType::size, _1), boost::bind(&ObjType::size, _2)) ); return largest; } // Largest template <std::size_t N> class String: public boost::array<char, N> { public: std::string str() const { if (this->back() == '\0') return std::string(this->data()); return std::string(this->data(), this->size()); } // str String() { this->assign('\0'); } String(const std::string& str_) { if (str_.size() > this->size()) throw std::runtime_error("String::ctor: str_ too big"); int copied = str_.copy(this->c_array(), this->size()); std::fill_n(this->begin() + copied, this->size() - copied, '\0'); } // ctor operator std::string() const { return str(); } }; // String using namespace std; int main(int argc, const char* argv[]) { // typedef String<64> ArgStr; // <-- This won't compile. typedef string ArgStr; // <-- This compiles/runs ok. vector<ArgStr> args; while (--argc) args.push_back(string(*++argv)); if (args.empty()) { cout << "no args!" << endl; return EXIT_FAILURE; } cout << "args="; copy(args.begin(), args.end(), ostream_iterator<string>(cout, " ")); cout << endl; vector<ArgStr>::iterator iter = Largest(args.begin(), args.end()); cout << "Largest arg is '" << string(*iter) << "'." << endl; return EXIT_SUCCESS; } // main

Terry G wrote:
Here's another (simplified) program I can't get to work. I'm trying to write a generic routine that finds the largest element of a sequence. It is assumed that element->size() is defined, as it is for boost::array and std::string. For some reason, the Largest template function works okay for std::strings, but not for boost::arrays. Can you tell me what is wrong?
This is a bug in boost::array, its size() function is static. You can remove the 'static' in your local copy and make it size_type size() const; to match TR1 and the future C++ standard.
template <class InIter> InIter Largest(InIter first, InIter last) { typedef typename boost::pointee<InIter>::type ObjType; InIter largest = std::max_element(first, last, boost::bind(std::less<std::size_t>(), boost::bind(&ObjType::size, _1),
Here: the problem is that &ObjType::size takes no arguments when ObjType is boost::array.
boost::bind(&ObjType::size, _2)) );
You can rewrite this as boost::bind(&ObjType::size, _1) < boost::bind(&ObjType::size, _2) BTW.
return largest; } // Largest
participants (2)
-
Peter Dimov
-
Terry G