Function Objects with Iterators

G

gexarchakos

Hi there,

Please give me at least a hint...
I have a problem implementing a function object with parameters two
iterators. That is:

A class 'node' produces messages using a routing policy. The routing
policy needs to take the node's neighbours and return a subset of them
based on several criteria. Each message may have different routing
policy. Thus, the policy should be specified while the new message is
produced. The policy should be a different class that can be inherited
and be able to take the (begin,end) iterators of the neighbour list
and return a std::stack of a subset of them.

The node should not reveal any of its internal structures, not even
the neighbours structure. This is why I created a templated function
object but I do not know how to declare the two iterators to be
general without having to specify their exact type.

template<class _TYPE> class router {
public:
// function to take the start and end iterators of a container and
return a subset of them in a stack.
// it decides using further inheritance which routing policy will be
used for each message
std::stack<_TYPE> operator()(iterator _begin, iterator _end);
};

template<class _MSG, class _CLK> class node { //this is a node
class with MESSAGE and CLOCK parameters
private:
// map holding node's neighbours and their expiry time
std::map<node<_MSG, _CLK>*, _CLK> _fanin, _fanout;
public:
// function to produce a message ready to deliver with the actual
content, expiry and routing policy
node<_MSG, _CLK>& produce(_MSG _msg, _CLK _clock, router _rout);
};

The user of the node::produce funtion does not need to specify the
exact iterator type since than would violate the principle of hiding
the neighbour's structure.

I need for the iterators a form so that I declare & define & use the
produce function without having to specify std::map<node<_MSG, _CLK>*,
_CLK>::iterator.

Please, help me or post a an idea that has the same effect.

Thanks in advance,
-- George
 
J

John Harrison

gexarchakos said:
Hi there,

Please give me at least a hint...
I have a problem implementing a function object with parameters two
iterators. That is:

A class 'node' produces messages using a routing policy. The routing
policy needs to take the node's neighbours and return a subset of them
based on several criteria. Each message may have different routing
policy. Thus, the policy should be specified while the new message is
produced. The policy should be a different class that can be inherited
and be able to take the (begin,end) iterators of the neighbour list
and return a std::stack of a subset of them.

The node should not reveal any of its internal structures, not even
the neighbours structure. This is why I created a templated function
object but I do not know how to declare the two iterators to be
general without having to specify their exact type.

template<class _TYPE> class router {
public:
// function to take the start and end iterators of a container and
return a subset of them in a stack.
// it decides using further inheritance which routing policy will be
used for each message
std::stack<_TYPE> operator()(iterator _begin, iterator _end);
};

template<class _MSG, class _CLK> class node { //this is a node
class with MESSAGE and CLOCK parameters
private:
// map holding node's neighbours and their expiry time
std::map<node<_MSG, _CLK>*, _CLK> _fanin, _fanout;
public:
// function to produce a message ready to deliver with the actual
content, expiry and routing policy
node<_MSG, _CLK>& produce(_MSG _msg, _CLK _clock, router _rout);
};

The user of the node::produce funtion does not need to specify the
exact iterator type since than would violate the principle of hiding
the neighbour's structure.

I need for the iterators a form so that I declare & define & use the
produce function without having to specify std::map<node<_MSG, _CLK>*,
_CLK>::iterator.

Please, help me or post a an idea that has the same effect.

Thanks in advance,
-- George

I think I understand you.

Write your template so that the iterator is the template parameter

template<class _ITER>
class router
{
public:
std::stack<typename _ITER::value_type> operator()(_ITER begin,
_ITER end);
};

All iterators have a member called value_type which is the type that the
iterator refers to.

John
 
G

gexarchakos

Many thanks John,

this would be a possible solution but the problem that appears now is
that when I call
node<_MSG,_CLK>::produce(_msg, _clock, router<std::map<node<_MSG,
_CLK>*,_CLK>::iterator>());
I need to know that the neighbours are in a map structure so that to
initialize the 'router' with this specific iterator.
e.g. if i have a function

void test() {
...
node<int,int> _n;
_n.produce(8,2,router<std::map<node<_MSG,
_CLK>*,_CLK>::iterator>());
}

This is something I need to avoid. The test function is outside the
class 'node' but still needs to know the neighbours structure.

However, your solution had something that really helped:
std::stack<typename _ITER::value_type> ... (good point)

What if:
class router {
public:
template<class _ITER> std::stack<typename _ITER::value_type>
operator()(_ITER _begin, _ITER _end);
};

This, I think, would solve the problem above but poses a new one:
template functions cannot be virtual so this posses some kind of
inheritance problem...

Any idea is welcome... and again many thanks John!

-- George
 
A

Alan Johnson

gexarchakos said:
What if:
class router {
public:
template<class _ITER> std::stack<typename _ITER::value_type>
operator()(_ITER _begin, _ITER _end);
};

A problem you are bound to run into using "_ITER::value_type" is that
pointers can be iterators, but obviously don't have a member called
"value_type".

Fortunately the standard anticipated this and provides an
"iterator_traits" template to solve the problem. You use it like:
std::iterator_traits<_ITER>::value_type

For most iterators this just becomes "_ITER::value_type", but for
pointer types it becomes the type the pointer points to.
 
R

red floyd

John said:
gexarchakos said:
[redacted]
template<class _TYPE> class router {
public:
// function to take the start and end iterators of a container
and
return a subset of them in a stack.
// it decides using further inheritance which routing policy
will be
used for each message
std::stack<_TYPE> operator()(iterator _begin, iterator _end);
};

template<class _MSG, class _CLK> class node { //this is a node
class with MESSAGE and CLOCK parameters
private:
// map holding node's neighbours and their expiry time
std::map<node<_MSG, _CLK>*, _CLK> _fanin, _fanout;
public:
// function to produce a message ready to deliver with the actual
content, expiry and routing policy
node<_MSG, _CLK>& produce(_MSG _msg, _CLK _clock, router _rout);
};

[redacted]
template<class _ITER>
class router
{
public:
std::stack<typename _ITER::value_type>
operator()(_ITER begin, _ITER end);
};

Both gexarchakos and John's code is improper. Any identifier with a
leading underscore followed by an uppercase letter is reserved to the
implementation.

Use TYPE_, MSG_, CLK_, ITER_ instead.
 
G

George Exarchakos

John said:
gexarchakos said:
[redacted]
template<class _TYPE> class router {
public:
// function to take the start and end iterators of a container
and
return a subset of them in a stack.
// it decides using further inheritance which routing policy
will be
used for each message
std::stack<_TYPE> operator()(iterator _begin, iterator _end);
};
template<class _MSG, class _CLK> class node { //this is a node
class with MESSAGE and CLOCK parameters
private:
// map holding node's neighbours and their expiry time
std::map<node<_MSG, _CLK>*, _CLK> _fanin, _fanout;
public:
// function to produce a message ready to deliver with the actual
content, expiry and routing policy
node<_MSG, _CLK>& produce(_MSG _msg, _CLK _clock, router _rout);
};
[redacted]
template<class _ITER>
class router
{
public:
std::stack<typename _ITER::value_type>
operator()(_ITER begin, _ITER end);
};

Both gexarchakos and John's code is improper. Any identifier with a
leading underscore followed by an uppercase letter is reserved to the
implementation.

Use TYPE_, MSG_, CLK_, ITER_ instead.

Thank you red floyd for your comment... One more thing I didn't know!
However, any compilation/building phase of my code didn't catch this.
Anyway, good to know for the future.

Thanks,
-- George
 
G

George Exarchakos

A problem you are bound to run into using "_ITER::value_type" is that
pointers can be iterators, but obviously don't have a member called
"value_type".

Fortunately the standard anticipated this and provides an
"iterator_traits" template to solve the problem. You use it like:
std::iterator_traits<_ITER>::value_type

For most iterators this just becomes "_ITER::value_type", but for
pointer types it becomes the type the pointer points to.

Hi Alan,

thank you for your reply. I have the Stroupstrup book in front of me
and I try to figure out how exactly I am going to use the
iterator_traits. My only problem is that it is again a templated-based
solution which is perfectly fine except for the case I want to use
inheritance (virtual) with the templated operator() of 'router'.

Correct me if I am wrong; I am supposed to write:
class router {
public:
template<class _ITER>
std::stack<std::iterator_traits<_ITER>::value_type> operator()(_ITER
_begin, _ITER _end);
};

If yes, then what if I what inheritance as well? Routing policies must
around 4-5 and I was planing to create a router abstract base class
with some subclasses to implement the actual policies.

Many thanks,
-- George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top