//
// Implements a basic crappy type named A
// -------------------------------------------------
class A
{
protected:
int i;
public:
A();
A(int value);
virtual ~A();
public:
void setInt(const int& value) { i = value; }
int& getInt() const { return (int &)i; };
};
//
// Defines an Action to be performs on list
// -------------------------------------------------
template <typename T> class Action
{
public:
virtual void operator() (T& obj) = 0;
};
//
// Implements a basic Adder action for list of A
// -------------------------------------------------
class Adder : public Action<A>
{
public:
void operator() (A& obj)
{
obj.setInt( obj.getInt() + 1 );
}
};
//
// Defines an generic List of type T
// -------------------------------------------------
template <typename T> class List
{
private:
std::list<T> innerList;
public:
/* There's alot of others methods not importants here */
void ForEach(Action<T>& action)
{
std::list<T>::iterator iter;
for(iter = innerList.begin(); iter != innerList.end(); iter++)
{
T item = (T)*iter;
action(item);
}
}
};
//
// The Test Program
// -------------------------------------------------
int main()
{
List<A> myList;
myList.Add(A(0));
myList.Add(A(1));
myList.Add(A(2));
myList.Add(A(3));
myList.Add(A(4));
myList.Add(A(5));
myList.ForEach(Adder());
}
Hummm... Templated List, STL, Generics, C++ ...
Hi all,
I was playing around with templated lists. I was trying to implements a templated list in C++ that looked like the .NET equivalent.
There was 2 methods in the .NET List class that gave and still give me some headhaches:
- T Find(Predicate<T> math);
- void ForEach(Action<T> match);
I finally fix the Find method and it's working like a charm. Now, i'm trying to get the ForEach method to work. Below is my current implementation:
This code compiles and works fine, excepts it doesnt works as expected ;). The list doesn't get "updated". Before and After the call to the ForEach method the list is: 0, 1, 2, 3, 4, 5.
It's probably a basic error or misunderstanding. I'm sure it has to do with the std::list that i'm using as my innerList. The code obj.setInt( obj.getInt() + 1 ); works and when i'm back to the ForEach method the referenced object's value is valid, but for some reason the referenced object doesn't get updated in the innerList.
Can someone helps me understand why?
Thanks,
Jonathan
Quote:T item = (T)*iter;
action(item);
In your case, your type T is A.
This means your item is a COPY of the contents of your list.
First, I would advise strongly against using ANY C-style casts in your code. You don't know what a C-style cast does. Use dynamic_cast, reinterpret_cast, static_cast or the good-old implicit casting.
Second, I would advise a slightly different signature for your ForEach method.
The result:
template<typename Action>void ForEach(Action& action) { {for(internal_iterator it = innerList.begin(); it != innerList.end(); ++it) { action(*it); }}}
Now anything that accepts the contents of your list can be passed to ForEach.
Also, note that the stl already has a foreach function.
[edit:
Agreed]
It should be:
That said, I don't quite see the purpose of giving std::list a .NET-like interface.
jfl.
Quote:Second, I would advise a slightly different signature for your ForEach method.
[...]
Agreed]
It should be:
for( iter = innerList.begin(); iter != innerList.end(); ++iter ) { T &item = *iter; action(item);}
That said, I don't quite see the purpose of giving std::list a .NET-like interface.
jfl.
Also assigning a temporary to a non-constant reference is a big no, no. Only constant references with literals or temporaries have defined behaviour.
Quote:Original post by jflanglois
That said, I don't quite see the purpose of giving std::list a .NET-like interface.
jfl.
++
The STL actually defines functions like find and for_each:
#include <iostream>#include <list>#include <algorithm>// Our crappy classclass Foo{public: Foo(void) : m_value(0) {} Foo(int value) : m_value(value) {} ~Foo(void) {}; int value(void) const {return m_value;} void setValue(int value) {m_value = value;}private: int m_value;};// A crappy functorstruct FooAdder : public std::unary_function<Foo &, void>{ void operator()(Foo &foo) { foo.setValue(foo.value() + 1); }};// A (not so?) crappy functorstruct FooPrinter : public std::unary_function<const Foo &, void>{ FooPrinter(std::ostream &os) : m_os(os) {}; void operator()(const Foo &foo) { m_os << foo.value() << " "; }private: std::ostream &m_os;};int main(void){ std::list<Foo> fooList; fooList.push_back(Foo(0)); fooList.push_back(Foo(1)); fooList.push_back(Foo(2)); fooList.push_back(Foo(3)); fooList.push_back(Foo(4)); fooList.push_back(Foo(5)); std::cout << "Before executing FooAdder on the list:" << std::endl; std::for_each(fooList.begin(), fooList.end(), FooPrinter(std::cout)); std::cout << std::endl; std::for_each(fooList.begin(), fooList.end(), FooAdder()); std::cout << "After executing FooAdder on the list:" << std::endl; std::for_each(fooList.begin(), fooList.end(), FooPrinter(std::cout)); std::cout << std::endl; return 0;}
Quote:Original post by snk_kid
Also assigning a temporary to a non-constant reference is a big no, no. Only constant references with literals or temporaries have defined behaviour.
*it returns a temporary?
For most iterators *iter is a reference. However, for some iterators, notably input iterators that aren't also forward iterators and for the demonic bastard stepchild of the container world, std::vector<bool>, *iter will be a temporary.
In those cases, it won't be castable to a T const& nor a T&.
That does make the problem interesting. :)
To solve it, your Action should look more like:
so it can accept "pseudo-refs" that override operator T, operator= and copy-constructors.
That does make the problem interesting. :)
To solve it, your Action should look more like:
struct Action { template<typename T> void operator()(RefOf<T>::type t);};
so it can accept "pseudo-refs" that override operator T, operator= and copy-constructors.
Quote:Original post by NotAYakkQuote:Original post by snk_kid
Also assigning a temporary to a non-constant reference is a big no, no. Only constant references with literals or temporaries have defined behaviour.
*it returns a temporary?
I never saw your code, i was referring to LowRad's code i.e myList.ForEach(Adder()); where ForEach takes a non-constant reference and he is passing a temporary which is bad. If he wants to pass a temporary of polymorphic type and behaves polymorphically he has to use a constant reference.
I wouldn't be surprised if he has similar code scattered around else where.
What exactly is the difference between using a const and non-const reference for temporaries in a situation like this? The reference is not being held outside the scope of the function call and I don't see anything wrong with modifying the temporary or calling non-const functions on it.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement