By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,836 Members | 1,703 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,836 IT Pros & Developers. It's quick & easy.

pointer_protector template

P: n/a
say i have a function object silly that takes a const ref to clowns

class silly : public std::unary_function<const clown&, bool>
{
...
}

and then i decide to feed it a bunch of pointers to clowns:

for_each(clown_pointers.begin(), clown_pointers.end(), silly());

of course this doesn't work. i would like some magic template that
makes it work like this:

for_each(clown_pointers.begin(), clown_pointers.end(),
pointer_protector(silly()));

so actually pointer_protector would be an overloaded function template,
which knows to check for whether or not it's getting a
std::unary_function<> or a std::binary_function<>, and then it would
spit out a corresponding unary pointer protector or binary pointer
protector. for the rest of this discussion, i will stick t talking
about the unary pointer protector and leave the binary pointer
protector as an exercise. here is my unary pointer protector template:

template<typename Arg, typename Res>
class unary : public std::unary_function<Arg*, Res>
{
public:

unary(const std::unary_function<Arg, Res>& f) : f(f)
{}

Res
operator() (Arg* a) //27
{ //28
return f(*a); //29
} //30
//31
private:
std::unary_function<Arg, Res> f;
};

this does not work - when i create a function object and encapsulate in
a pointer protector like this:

struct print_it : public std::unary_function<int, int>
{
...
}

int
main()
{
for_each( foo.begin(), foo.end(),
unary<print_it::argument_type,
print_it::result_type>(print_it()) );
}

i get an error like this:

unary.cpp:29 error: no match for call to `(unary_function<int, int>)
(int &)'

using g++ via gfilt on FreeBSD 5.4-STABLE. so what is the right way to
write a pointer to reference encapsulating translator? does it already
exist?

Jul 23 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
jsnX wrote:
using g++ via gfilt on FreeBSD 5.4-STABLE. so what is the right way to
write a pointer to reference encapsulating translator? does it already
exist?


Yes, for example you can use boost::lambda (check www.boost.org). It
implements the lambda calculus and is capable of creating these functors
for you automatically. Check their examples.

Another option would be to create two templates for your functor using
partial specialization: One working on pure objects and one working on
pointers to objects.
You can use boost::type_traits to check whether it's a pointer type or
not and then let the compiler instantiate the correct template
automagically.

--
Matthias Kaeppler
Jul 23 '05 #2

P: n/a
say i can't use boost, then what?

Jul 23 '05 #3

P: n/a
I would really like to know why my code does not work.

Jul 23 '05 #4

P: n/a
jsnX wrote:
I would really like to know why my code does not work.

I've felt the same way many times.


Brian
Jul 23 '05 #5

P: n/a
jsnX wrote:
I would really like to know why my code does not work.


The code you posted was more than incomplete. Please post your real
code, so we can take a look at it.

One "solution" not using boost or related would be to set flags and then
utilize template specialization to produce functors with different behavior.

//-----

template <bool is_pointer, bool is_binary>
struct silly: unary_function<const clown&, bool> {
bool operator() (const clown& arg) {}
};

template <true, false>
struct silly: unary_function<const clown*, bool> {
bool operator() (const clown* arg) {}
};

template <false, true>
struct silly: binary_function<const clown&, const clown&, bool> {
bool operator() (const clown& arg1, const clown& arg2) {}
};

template <true, true>
struct silly: binary_function<const clown*, const clown*, bool> {
bool operator() (const clown* arg1, const clown* arg2) {}
};

//-----

You can then feed it to STL algos using the same name, but you have to
provide the template arguments. For example, if you have a collection
coll which holds pointers to clown objects, you can do something like this:

for_each(coll.begin(), coll.end(), silly<true, false>());

Is that what you mean?

--
Matthias Kaeppler
Jul 24 '05 #6

P: n/a
my real code is this:

===========test.cpp============

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <utility>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <map>
struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " " << std::endl;
return i;
}
};

template<typename Arg, typename Res>
class unary : public std::unary_function<Arg*, Res>
{
public:

unary(const std::unary_function<Arg, Res>& f) : f(f)
{}

Res
operator() (Arg* a)
{
return f(*a); //35
}

private:
std::unary_function<Arg, Res> f;
};
int
main(int argc, char* argv[])
{
using namespace std;

vector<int*> foo;

cout << "foo [ ";
for(int i = 0; i < 10; i++)
{
int* kittens = new int(rand() % 32);
cout << *kittens << " ";
foo.push_back(kittens);
}
cout << "]" << endl;

cout << "foo [ ";
for_each( foo.begin(), foo.end(),
unary< print_it::argument_type,
print_it::result_type >(print_it()) ); //62
cout << "]" << endl;
exit(0);
}

===================================

and it fails like this:

===================================
test.cpp: In member function `int unary<int, int>::operator()(int *)':
stl_algo.h:158: instantiated from
`unary<
int, int
for_each(

vector<int *>::iterator, vector<int *>::iterator, unary<int,
int>
)'
test.cpp:62: instantiated from here
test.cpp:35: error: no match for call to `(unary_function<int, int>)
(int &)'
===================================

Jul 24 '05 #7

P: n/a
jsnX wrote:
my real code is this:

===========test.cpp============

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <utility>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <map>
struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " " << std::endl;
return i;
}
};

template<typename Arg, typename Res>
class unary : public std::unary_function<Arg*, Res>
{
public:

unary(const std::unary_function<Arg, Res>& f) : f(f)
{}

Res
operator() (Arg* a)
{
return f(*a); //35
}

private:
std::unary_function<Arg, Res> f;
};


Try

template<typename Arg, typename Res, typename Function>
class unary : public std::unary_function<Arg*, Res>
{
public:

unary(const Function& f) : f(f)
{}

Res
operator() (Arg* a)
{
return f(*a); //35
}

private:
Function f;
};

Why? unary_function does not include an operator() which you are
trying to use. unary_function just contain traits information.

Which basically means you can deduce Arg and Res from Function
Function::result_type operator()typename Function::argument_type* a);

for_each( foo.begin(), foo.end(),
unary< print_it::argument_type,
print_it::result_type,print_it >(print_it()) );

Or
for_each( foo.begin(), foo.end(),
unary< print_it >(print_it()) );

If you just use typename Function in the template definition
template<typename Function>
class unary : public std::unary_function< typename
Function::argument_type *, typename Function::result_type>

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Jul 24 '05 #8

P: n/a
Tobias Blomkvist wrote:
Which basically means you can deduce Arg and Res from Function
Function::result_type operator()typename Function::argument_type* a);
typename Function::result_type operator()
(typename Function::argument_type * a);
for_each( foo.begin(), foo.end(),
unary< print_it::argument_type,
print_it::result_type,print_it >(print_it()) );


Since in this case unary knows what function object it will recieve,
you could replace it with: (constructor argument not needed)

unary<print_it>()(7);

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Jul 24 '05 #9

P: n/a
> Since in this case unary knows what function object it
will recieve, you could replace it with:
(constructor argument not needed)

unary<print_it>()(7);


If I pass in '7' as in your example above, won't it get read as a
pointer and make the code puke at runtime?

Jul 24 '05 #10

P: n/a
jsnX sade:
Since in this case unary knows what function object it
will recieve, you could replace it with:
(constructor argument not needed)

unary<print_it>()(7);

If I pass in '7' as in your example above, won't it get read as a
pointer and make the code puke at runtime?


Yeah, ignore that last statement.

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Jul 24 '05 #11

P: n/a
so basically, it works. here's the source that i'm working with now:

==============deref.cpp====================
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <utility>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <map>

namespace deref
{

template<class F>
class unary_function
: public std::unary_function< typename F::argument_type*,
typename F::result_type >
{
public:

unary_function(const F& f) : f(f)
{}

typename F::result_type
operator() (typename F::argument_type* a)
{
return f(*a);
}

private:
F f;
};

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< std::unary_function<Arg, Res> >(f);
}
template<class F>
class binary_function
: public std::binary_function< typename F::first_argument_type*,
typename F::second_argument_type*,
typename F::result_type >
{
public:

binary_function(const F& f) : f(f)
{}

typename F::result_type
operator() ( typename F::first_argument_type* _1,
typename F::second_argument_type* _2 )
{
return f(*_1, *_2);
}

private:
F f;
};

template<typename Arg_1, typename Arg_2, typename Res>
binary_function< std::binary_function<Arg_1, Arg_2, Res> >
create(const std::binary_function<Arg_1, Arg_2, Res>& f)
{
return binary_function< std::binary_function<Arg_1, Arg_2, Res>
(f); }

}
=======================================

====================test.cpp==============
#include "deref.cpp"
struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " ";
return i;
}
};

int
main(int argc, char* argv[])
{
using namespace std;

vector<int*> foo;

cout << "foo [ ";
for(int i = 0; i < 10; i++)
{
int* kittens = new int(rand() % 32);
cout << *kittens << " ";
foo.push_back(kittens);
}
cout << "]" << endl;

cout << "foo [ ";
for_each( foo.begin(), foo.end(),
deref::unary_function<print_it>(print_it()) );
cout << "]" << endl;
exit(0);
}
=======================================

The two deref::create(...) functions in deref.cpp don't do what I would
like, however. When I try this call for the for_each statement:

for_each( foo.begin(), foo.end(),
deref::create(print_it()) );

i get the error that goes

no match for call to `(unary_function<int, int>) (int &)'

which i guess is because my print_it object gets cast to
std::unary_function when it enters my create function, and then the
deref::unary_function object is instantiated with a std::unary_function
object and not a print_it object! Is there a way to rewrite
deref::create sort of like this:

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< std::unary_function<Arg, Res> >(f);
}
template<class F>
class binary_function
: public std::binary_function< typename F::first_argument_type*,
typename F::second_argument_type*,
typename F::result_type >
{
public:

binary_function(const F& f) : f(f)
{}

typename F::result_type
operator() ( typename F::first_argument_type* _1,
typename F::second_argument_type* _2 )
{
return f(*_1, *_2);
}

private:
F f;
};

template<typename Arg_1, typename Arg_2, typename Res>
binary_function< std::binary_function<Arg_1, Arg_2, Res> >
create(const std::binary_function<Arg_1, Arg_2, Res>& f)
{
return binary_function< std::binary_function<Arg_1, Arg_2, Res>(f); }

}
=======================================

====================test.cpp==============
#include "deref.cpp"
struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " ";
return i;
}
};

int
main(int argc, char* argv[])
{
using namespace std;

vector<int*> foo;

cout << "foo [ ";
for(int i = 0; i < 10; i++)
{
int* kittens = new int(rand() % 32);
cout << *kittens << " ";
foo.push_back(kittens);
}
cout << "]" << endl;

cout << "foo [ ";
for_each( foo.begin(), foo.end(),
deref::unary_function<print_it>(print_it()) );
cout << "]" << endl;
exit(0);
}
=======================================

The two deref::create(...) functions in deref.cpp don't do what I would
like, however. When I try this call for the for_each statement:

for_each( foo.begin(), foo.end(),
deref::create(print_it()) );

i get the error that goes

no match for call to `(unary_function<int, int>) (int &)'

which i guess is because my print_it object gets cast to
std::unary_function when it enters my create function, and then the
deref::unary_function object is instantiated with a std::unary_function
object and not a print_it object! Is there a way to rewrite
deref::create sort of like this:

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< std::unary_function<Arg, Res> >(f);
}
template<class F>
class binary_function
: public std::binary_function< typename F::first_argument_type*,
typename F::second_argument_type*,
typename F::result_type >
{
public:

binary_function(const F& f) : f(f)
{}

typename F::result_type
operator() ( typename F::first_argument_type* _1,
typename F::second_argument_type* _2 )
{
return f(*_1, *_2);
}

private:
F f;
};

template<typename Arg_1, typename Arg_2, typename Res>
binary_function< std::binary_function<Arg_1, Arg_2, Res> >
create(const std::binary_function<Arg_1, Arg_2, Res>& f)
{
return binary_function< std::binary_function<Arg_1, Arg_2, Res>(f);

}

}
=======================================

====================test.cpp==============
#include "deref.cpp"
struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " ";
return i;
}
};

int
main(int argc, char* argv[])
{
using namespace std;

vector<int*> foo;

cout << "foo [ ";
for(int i = 0; i < 10; i++)
{
int* kittens = new int(rand() % 32);
cout << *kittens << " ";
foo.push_back(kittens);
}
cout << "]" << endl;

cout << "foo [ ";
for_each( foo.begin(), foo.end(),
deref::unary_function<print_it>(print_it()) );
cout << "]" << endl;
exit(0);
}
=======================================

The two deref::create(...) functions in deref.cpp don't do what I would
like, however. When I try this call for the for_each statement:

for_each( foo.begin(), foo.end(),
deref::create(print_it()) );

i get the error that goes

no match for call to `(unary_function<int, int>) (int &)'

which i guess is because my print_it object gets cast to
std::unary_function when it enters my create function, and then the
deref::unary_function object is instantiated with a std::unary_function
object and not a print_it object! Is there a way to rewrite
deref::create sort of like this:

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< what_so_ever_f_is >(f);
}

Jul 24 '05 #12

P: n/a
so basically, it works. here's the source that i'm working with now:

==============deref.cpp====================
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <utility>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <map>

namespace deref
{

template<class F>
class unary_function
: public std::unary_function< typename F::argument_type*,
typename F::result_type >
{
public:

unary_function(const F& f) : f(f)
{}

typename F::result_type
operator() (typename F::argument_type* a)
{
return f(*a);
}

private:
F f;
};

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< std::unary_function<Arg, Res> >(f);
}

template<class F>
class binary_function
: public std::binary_function< typename F::first_argument_type*,
typename F::second_argument_type*,
typename F::result_type >
{
public:

binary_function(const F& f) : f(f)
{}

typename F::result_type
operator() ( typename F::first_argument_type* _1,
typename F::second_argument_type* _2 )
{
return f(*_1, *_2);
}

private:
F f;
};

template<typename Arg_1, typename Arg_2, typename Res>
binary_function< std::binary_function<Arg_1, Arg_2, Res> >
create(const std::binary_function<Arg_1, Arg_2, Res>& f)
{
return binary_function< std::binary_function<Arg_1, Arg_2, Res>
(f);


}

}

=======================================

====================test.cpp==============
#include "deref.cpp"

struct print_it : public std::unary_function<int, int>
{
int
operator() (int i)
{
std::cout << i << " ";
return i;
}
};

int
main(int argc, char* argv[])
{
using namespace std;

vector<int*> foo;

cout << "foo [ ";
for(int i = 0; i < 10; i++)
{
int* kittens = new int(rand() % 32);
cout << *kittens << " ";
foo.push_back(kittens);
}
cout << "]" << endl;

cout << "foo [ ";
for_each( foo.begin(), foo.end(),
deref::unary_function<print_it>(print_it()) );
cout << "]" << endl;

exit(0);
}

=======================================

The two deref::create(...) functions in deref.cpp don't do what I would
like, however. When I try this call

for_each( foo.begin(), foo.end(),
deref::create(print_it()) );

for the for_each statement i get the error that goes

no match for call to `(unary_function<int, int>) (int &)'

which i guess is because my print_it object gets cast to
std::unary_function when it enters my create function, and then the
deref::unary_function object is instantiated with a std::unary_function
object and not a print_it object! Is there a way to rewrite
deref::create

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< what_so_ever_f_is >(f);
}

so that it puts the right type in where I need it?

Jul 24 '05 #13

P: n/a
jsnX sade:
The two deref::create(...) functions in deref.cpp don't do what I would
like, however. When I try this call

for_each( foo.begin(), foo.end(),
deref::create(print_it()) );

for the for_each statement i get the error that goes

no match for call to `(unary_function<int, int>) (int &)'

which i guess is because my print_it object gets cast to
std::unary_function when it enters my create function, and then the
deref::unary_function object is instantiated with a std::unary_function
object and not a print_it object! Is there a way to rewrite
deref::create

template<typename Arg, typename Res>
unary_function< std::unary_function<Arg, Res> >
create(const std::unary_function<Arg, Res>& f)
{
return unary_function< what_so_ever_f_is >(f);
}

so that it puts the right type in where I need it?

Here's one solution, but it will only work if the function
object is derived from either virtual_binary_function
or unary_virtual_function

template<typename A1,typename A2, typename R>
class virtual_binary_function : public std::binary_function<A1,A2,R>
{
public:
virtual R operator()(A1,A2) = 0;
};

template<typename A, typename R>
class virtual_unary_function : public std::unary_function<A,R>
{
public:
virtual R operator()(A) = 0;
};

template<class F>
class unary_function
: public std::unary_function< typename F::argument_type*,
typename F::result_type >
{
public:

unary_function(const F& f) : f(f)
{}

typename F::result_type
operator() (typename F::argument_type* a)
{
return f(*a);
}

private:
const F & f; // <-!! Notice const and reference
};

struct print_it : public virtual_unary_function<int, int>
{
int operator() (int i)
{
std::cout << i << " ";
return i;
}
};

template<typename A, typename B>
unary_function< virtual_unary_function<A,B> >
create(const virtual_unary_function<A,B>& uf)
{
return unary_function< virtual_unary_function<A,B> >(uf);
}

template<typename A, typename B, typename C>
binary_function< virtual_binary_function<A,B,C> >
create(const virtual_binary_function<A,B,C>& uf)
{
return binary_function< virtual_binary_function<A,B,C> >(uf);
}

for_each( foo.begin(),foo.end(),create(print_it()) );

Tobias
--
IMPORTANT: The contents of this email and attachments are confidential
and may be subject to legal privilege and/or protected by copyright.
Copying or communicating any part of it to others is prohibited and may
be unlawful.
Jul 24 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.