From: Maitre Bart on
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

"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
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
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! ]