|
From: Maitre Bart on 14 Nov 2006 19:35 I made a functor that outputs a custom-formatted string given a pair as input: class pair2string { public: pair2string() : _sep(" => ") {} pair2string(const string& sep_) : _sep(sep_) {} template <typename F, typename S> string operator()(pair<F,S>& p_) const { ostringstream oss; oss << p_.first << _sep << p_.second; return oss.str(); } private: const string _sep; }; It works fine for: cout << pair2string()(*m.begin()) << "\n"; where m is a map<string,int> . But if one of the pair arguments is a pair, there is a no-match, as for: cout << pair2string()(make_pair("test",*m.begin())) << "\n"; So, I tried to add this overload in my class to solve the no-match: template <typename F, typename SF, typename SS> string operator()(pair<F,pair<SF,SS> >& p_) const { ostringstream oss; oss << p_.first << _sep << pair2string(_sep)(p_.second); return oss.str(); } But I still get a no-match from the compiler. Anyone has any idea why and have a solution to the no-match? In the end, I'd like to overload the 2 other possibilities: template <typename FF, typename FS> string operator()(pair<pair<FF,FS>,S>& p_) const { ostringstream oss; oss << pair2string(_sep)(p_.first) << _sep << p_.second; return oss.str(); } template <typename FF, typename FS, typename SF, typename SS> string operator()(pair<pair<FF,FS>,pair<SF,SS> >& p_) const { ostringstream oss; oss << pair2string(_sep)(p_.first) << _sep << pair2string(_sep)(p_.second); return oss.str(); } Thank you for helping me. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mads Elvheim on 15 Nov 2006 10:16 "Maitre Bart" <maitrebart(a)excite.com> wrote in message news:1163534340.976255.271780(a)f16g2000cwb.googlegroups.com... >I made a functor that outputs a custom-formatted string given a pair as > input: > class pair2string > { > public: > pair2string() : _sep(" => ") {} > pair2string(const string& sep_) : _sep(sep_) {} > > template <typename F, typename S> > string operator()(pair<F,S>& p_) const > { > ostringstream oss; > oss << p_.first << _sep << p_.second; > return oss.str(); > } > private: > const string _sep; > }; > It works fine for: > cout << pair2string()(*m.begin()) << "\n"; > where m is a map<string,int> . > But if one of the pair arguments is a pair, there is a no-match, as > for: > cout << pair2string()(make_pair("test",*m.begin())) << "\n"; > So, I tried to add this overload in my class to solve the no-match: > template <typename F, typename SF, typename SS> > string operator()(pair<F,pair<SF,SS> >& p_) const > { > ostringstream oss; > oss << p_.first << _sep << pair2string(_sep)(p_.second); > return oss.str(); > } > But I still get a no-match from the compiler. Anyone has any idea why > and have a solution to the no-match? ostringstream oss; oss << p_.first << _sep << p_.second; The problem is that you are assuming that p_.first and p_.second are basic types, and/or have a valid operator <<. std::make_pair(some_string, some_map) is not a map which will give a match in your case, because the map in the map doesn't have a valid operator <<. Your actual object would reside in p_.second.first or p_second.second. (add a .first or .second for each layer of maps) So you have to decide whether you want p_.second.first or p_.second.second. Functional programming has never been C++ strongest side, I'm afraid. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Carl Barron on 15 Nov 2006 10:18 In article <1163534340.976255.271780(a)f16g2000cwb.googlegroups.com>, Maitre Bart <maitrebart(a)excite.com> wrote: > I made a functor that outputs a custom-formatted string given a pair as > input: > > class pair2string > { > public: > pair2string() : _sep(" => ") {} > pair2string(const string& sep_) : _sep(sep_) {} > > template <typename F, typename S> > string operator()(pair<F,S>& p_) const > { > ostringstream oss; > oss << p_.first << _sep << p_.second; > return oss.str(); > } > > private: > > const string _sep; > }; > > It works fine for: > > cout << pair2string()(*m.begin()) << "\n"; > > where m is a map<string,int> . > > But if one of the pair arguments is a pair, there is a no-match, as > for: > > cout << pair2string()(make_pair("test",*m.begin())) << "\n"; > > So, I tried to add this overload in my class to solve the no-match: > > template <typename F, typename SF, typename SS> > string operator()(pair<F,pair<SF,SS> >& p_) const > { > ostringstream oss; > oss << p_.first << _sep << pair2string(_sep)(p_.second); > return oss.str(); > } > > But I still get a no-match from the compiler. Anyone has any idea why > and have a solution to the no-match? > > In the end, I'd like to overload the 2 other possibilities: > > template <typename FF, typename FS> > string operator()(pair<pair<FF,FS>,S>& p_) const > { > ostringstream oss; > oss << pair2string(_sep)(p_.first) << _sep << p_.second; > return oss.str(); > } > > template <typename FF, typename FS, typename SF, typename SS> > string operator()(pair<pair<FF,FS>,pair<SF,SS> >& p_) const > { > ostringstream oss; > oss << pair2string(_sep)(p_.first) << _sep << > pair2string(_sep)(p_.second); > return oss.str(); > } > > Thank you for helping me. > we must determine which if any of the members of the pair is another pair. To do this I wrote these simple templates; template <bool B> struct bool_{}; typedef bool_<true> true_; typedef bool _<false> false_; template <typename T> struct is_pair{static const bool value = false;}; template <typename T,typename U> struct is_pair<std::pair<T,U> > { static const bool value = true;}; now let operator () (std::pair<T,U> const &p) call an overloaded private member for each of the four possibilities as shown below. if the argument of the pair is a pair call operator () recursively else just use it. This compiled with CW 10 and runs correctly. #include <utility> #include <string> #include <sstream> #include <iostream> template <bool B> struct bool_{}; typedef bool_<true> true_; typedef bool_<false> false_; template <typename T> struct is_pair {static const bool value = false;}; template <typename T,typename U> struct is_pair<std::pair<T,U> > { static const bool value = true;}; class pair2string { const std::string sep; template <class T,class U> std::string do_it(std::pair<T,U> const &p,false_,false_) { std::ostringstream oss; oss << p.first << sep << p.second ; return oss.str(); } template <class T,class U> std::string do_it(std::pair<T,U> const &p,false_,true_) { std::ostringstream oss; oss << p.first << sep << (this->operator()(p.second)); return oss.str(); } template <class T,class U> std::string do_it(std::pair<T,U> const &p,true_,false_) { std::ostringstream oss; oss << (this->operator())(p.first) << sep << p.second; return oss.str(); } template <class T,class U> std::string do_it(std::pair<T,U> const &p,true_,true_) { std::ostringstream oss; oss << (this->operator())(p.first) << sep << (this->operator())(p.second); return oss.str(); } public: explicit pair2string(const std::string &a="->") :sep(a){} template <class T,class U> std::string operator () (std::pair<T,U> const &p) { return this->do_it ( p, bool_<is_pair<T>::value>(), bool_<is_pair<U>::value>() ); } }; int main() { pair2string flatten; std::cout << flatten(std::make_pair(1,2)) << '\n'; std::cout << flatten(std::make_pair(1,std::make_pair(2,3))) << '\n'; std::cout << flatten(std::make_pair(std::make_pair(1,2),3)) << '\n'; std::cout << flatten(std::make_pair(std::make_pair(1,2),std::make_pair(3,4))) << '\n'; std::cout << flatten (std::make_pair(std::make_pair(std::make_pair(1,2),3),std::make_pair(4,5) )) << '\n'; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: dasjotre on 15 Nov 2006 16:55 Maitre Bart wrote: > I made a functor that outputs a custom-formatted string given a pair as > input: > > class pair2string > { > public: > pair2string() : _sep(" => ") {} > pair2string(const string& sep_) : _sep(sep_) {} > > template <typename F, typename S> > string operator()(pair<F,S>& p_) const > { > ostringstream oss; > oss << p_.first << _sep << p_.second; > return oss.str(); > } > > private: > > const string _sep; > }; > > It works fine for: > > cout << pair2string()(*m.begin()) << "\n"; > > where m is a map<string,int> . > > But if one of the pair arguments is a pair, there is a no-match, as > for: > > cout << pair2string()(make_pair("test",*m.begin())) << "\n"; first problem is that your pair2string::operator() takes a non const and make_pair returns temporary which can only be bound to a const reference second problem is that you don't have an operator where F or S can be pairs and there is no ostream << specialization for pairs > > So, I tried to add this overload in my class to solve the no-match: > > template <typename F, typename SF, typename SS> > string operator()(pair<F,pair<SF,SS> >& p_) const > { > ostringstream oss; > oss << p_.first << _sep << pair2string(_sep)(p_.second); > return oss.str(); > } > > But I still get a no-match from the compiler. Anyone has any idea why > and have a solution to the no-match? > > In the end, I'd like to overload the 2 other possibilities: > > template <typename FF, typename FS> > string operator()(pair<pair<FF,FS>,S>& p_) const > { > ostringstream oss; > oss << pair2string(_sep)(p_.first) << _sep << p_.second; > return oss.str(); > } > > template <typename FF, typename FS, typename SF, typename SS> > string operator()(pair<pair<FF,FS>,pair<SF,SS> >& p_) const > { > ostringstream oss; > oss << pair2string(_sep)(p_.first) << _sep << > pair2string(_sep)(p_.second); > return oss.str(); > } > the short version: (if you have a ostream<< defined for ::std::string) class pair2string { public: pair2string() : _sep(" => ") {} pair2string(const ::std::string & sep_) : _sep(sep_) {} template <typename T> ::std::string operator()(T const & p_) const { ::std::ostringstream oss; oss << p_; return oss.str(); } template <typename F, typename S> ::std::string operator()(::std::pair<F,S> const & p_) const { ::std::ostringstream oss; pair2string p2s(_sep); oss << p2s(p_.first) << _sep << p2s(p_.second); return oss.str(); } private: const ::std::string _sep; }; -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: iterator facade Next: using vector to encapulate a tree - non const copy constructors |