473,378 Members | 1,119 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

pointer_protector template

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
13 1600
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
say i can't use boost, then what?

Jul 23 '05 #3
I would really like to know why my code does not work.

Jul 23 '05 #4
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
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
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
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
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
> 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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Oplec | last post by:
Hi, I'm learning C++ as a hobby using The C++ Programming Language : Special Edition by Bjarne Stroustrup. I'm working on chpater 13 exercises that deal with templates. Exercise 13.9 asks for me...
31
by: nikola | last post by:
Hi all, I was working with a simple function template to find the min of two values. But since I would like the two values to be different (type) I dont know what kind of value (type) it will...
5
by: Gianni Mariani | last post by:
The spirit of this arguably pointless exercise, is that the numeric_limits<T> class could be replaced with a totally generic template of compile-time, template computed constants. The problem is...
2
by: Rudy Ray Moore | last post by:
Whenever I get any error with Vc++7.1/.net/2003, it is followed by huge ammounts of "template assistance" error messaging referencing template code (MTL) that has nothing to do with the error. ...
2
by: Alfonso Morra | last post by:
I have a class declared as ff: class __declspec(dllexport) A { public: A() ; A(const A&) A& operator=(const A&) ; ~A() ; void doThis(void) ;
19
by: aaragon | last post by:
Hi everyone. A very simple question. I would like to know what is better in terms of performance. I want to use a simple function to obtain the minimum of two values. One way could be using a...
3
by: Hamilton Woods | last post by:
Diehards, I developed a template matrix class back around 1992 using Borland C++ 4.5 (ancestor of C++ Builder) and haven't touched it until a few days ago. I pulled it from the freezer and...
45
by: charles.lobo | last post by:
Hi, I have recently begun using templates in C++ and have found it to be quite useful. However, hearing stories of code bloat and assorted problems I decided to write a couple of small programs...
9
by: Leo jay | last post by:
i'd like to implement a class template to convert binary numbers to decimal at compile time. and my test cases are: BOOST_STATIC_ASSERT((bin<1111,1111,1111,1111>::value == 65535));...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.