I have two different classes as below:
class text
{ };
class element
{ };
And I want to store them in the class node:
template <typename T>
class node
{
T cargo;
std::vector<void*> children;
node(T cargo) : cargo(cargo)
{ };
void add_child(T node)
{
this->children.push_back((void*) node);
}
}
So I would call the node this way storing both, text and element's:
element div;
text msg;
node<element> wrapper(div);
wrapper.add_child(msg);
EDIT: To get back the content I use T typedef type; and convert void pointer to (type*).
I know that's not very elegant nor functional, but I just can't figure out what's the correct way of doing that. So please tell me if this is practically acceptable and if it is not, how to do that in the proper manner.
Thanks in advance!
#include <vector>
using namespace std;
class Element {};
class Text {};
class Nothing {};
class Node
{
private:
vector< Node* > children_;
protected:
Node() {}
public:
void add( Node* p ) { children_.push_back( p ); }
virtual ~Node() {}
};
template< class Cargo >
class CargoNode
: public Node
{
private:
Cargo cargo_;
public:
CargoNode(): cargo_() {}
};
typedef CargoNode< Element > ElementNode;
typedef CargoNode< Text > TextNode;
typedef CargoNode< Nothing > RootNode;
int main()
{
RootNode* root = new RootNode;
root->add( new ElementNode );
root->add( new ElementNode );
root->add( new TextNode );
root->add( new ElementNode );
// Etc.
}
Cheers & hth.,
PS: Error checking, lifetime management, iteration etc. omitted in this example code.
I would say that void* is nearly always "bad" (for some definition of bad). Certainly, there are likely to be better ways of expressing what it is you're trying to do. If it were me writing this code and I knew the types of the values I was going to put in, then I would consider using a Boost.Variant. If I didn't (for example, this was supplied as a library to someone else to "fill up"), then I would use Boost.Any
For example:
template <class T, class U>
struct node
{
typedef boost::variant<T, U> child_type;
std::vector<child_type> children;
void add_child(T const &t)
{
children.push_back(t);
}
void add_child(U const &u)
{
children.push_back(u);
}
};
...
node<text, element> n;
n.add_child(text("foo"));
A non-boost typed union solution:
struct node
{
struct child
{
int type; // 0 = text; 1 = element
union
{
text* t;
element* e;
} u;
};
std::vector<child> children;
void add_child(text* t)
{
child ch;
ch.type = 0;
ch.u.t = t;
children.push_back(ch);
}
void add_child(element* e)
{
child ch;
ch.type = 1;
ch.u.e = t;
children.push_back(ch);
}
};
Note: you have to be a whole lot more careful about memory management with the typed union.
Define a shared base class for element and text and then add_child can take a pointer to the base class, and the vector can store pointers to the base class.
How would you get them back if you do this? From a void* there is no way to determine what is actually stored on the address.
Edit:
If you always do a cast into T* then you can simply take T* as the parameter.
If your container value is limited to a small number of types, you could achieve this using boost::variant as shown here:
#include <vector>
#include <boost/variant.hpp>
using namespace std;
class text
{ };
class element
{ };
template <typename T>
class node
{
T cargo;
static std::vector<boost::variant<text, element>> children;
node(const T& cargo) : cargo(cargo)
{ };
void add_child(const T& node)
{
children.push_back(boost::variant<text, element>(node));
}
};
I have taken the liberty of suggesting a couple of other mods - use const reference instead of pass-by-value on node constructor and add_child; make the container children static as I don't think it makes sense for each node<T> to have its own container. Locking would be required for multithreaded usage of add_child in this case. These comments apply whether you can use Boost or not in your final solution.
You can perform operations on the vector elements using either get or static_visitor - the latter is preferable since you can make this generic - as shown here. An example of vector iteration analogous to what you would use for this solution:
class times_two_generic
: public boost::static_visitor<>
{
public:
template <typename T>
void operator()( T & operand ) const
{
operand += operand;
cout << operand << endl;
}
};
std::vector< boost::variant<int, std::string> > vec;
vec.push_back( 21 );
vec.push_back( "hello " );
times_two_generic visitor;
std::for_each(
vec.begin(), vec.end()
, boost::apply_visitor(visitor)
);
Output is:
42
hello hello
First, there's no such a thing as "bad" to use a void pointer. Forget all the conventions and bla-blas, and do what's most appropriate for your case.
Now, in you specific case, if there's any connection between those two classes - you may declare a base class, so that those two will inherit it. Then, you may declare the vector of a pointer of that base class.
Related
I have a class that for some reasons needs to store a pair (say int,double) for each key, but whose interface only makes public one of the two values of the pair (int). One implementation may be
using namespace std;
class Foo {
public:
map<string,int> const & get() const {return external;}
void doStuff(string const & str) {
external.at(str);
internal.at(str);
}
private:
map<string,int> external;
map<string,double> internal;
};
The drawback is that doStuff has double lookup.
Another way is to store map<string,pair<int,double>> allin but then the accessor returning the whole map requires a copy.
The last way, of course, is to make the accessor more atomic by accessing a single key with a return allin.at(key).first;, which seems the best way but it breaks the interface I would like to provide.
I wonder, is there a way to avoid the double lookup in the "external/internal" version?
Another way could be to define a map entry with a private and a public value. Via a friend declaration the private value can be made visable to Foo class.
#include <iostream>
#include <string>
#include <map>
class Foo;
template<typename T1, typename T2>
struct my_map_entry
{
public:
my_map_entry()=default;
my_map_entry(T1 v, T2 pv)
{
value = v;
private_value = pv;
}
T1 value;
private:
T2 private_value;
friend class Foo;
};
class Foo {
public:
Foo(){
map["test"]=my_map_entry<int, double>(1, 2.0);
}
void doStuff(const std::string& str
{
auto entry = map.at(str);
std::cout<<"private_value: "<<entry.private_value<<std::endl;
}
std::map<std::string,my_map_entry<int, double>> map;
};
int main()
{
Foo test;
test.doStuff("test");
}
Given you just want the user to be able to retrieve the item, your get() method can be rewritten bearing that requirement in mind.
using namespace std;
class Foo {
public:
int *const get(string const &str) const {
auto it = map_.find(str)
return it == map_.end() ? nullptr : &it->first;
}
void doStuff(string const & str) {
map_.at(str);
}
private:
map<string,pair<int, double>> map_;
};
The idea is to return nullptr if the key was not found, or a pointer to the value if the key was found.
If instead you also want to be able to enumerate all the available ints, then you only have three choices:
Make your Foo class a map-like class, with its own iterators that wrap the ones from the inner map.
Use one of the available libraries to provide a view that helps you achieving the previous goal (like boost::transform_iterator)
As the other answer suggests, use a struct as the map's value and make one of its fields private, with possibly a conversion operator to int.
C++ allows one to define pointers to members of a class like:
struct A
{
int i;
};
void a()
{
int A::*p = &A::i;
}
but what if I want a pointer to a member that's on a deeper "level" like this?
struct A
{
int i;
struct B{int j;};
B b;
};
void a()
{
int A::*p = &A::b::j;
}
Theoretically it seems that if pointer to members are compiled to offets from the start of the object this could have been easily supported by the language although things like virtual/diamond inheritance would probably make this far too complicated
What's the easiest way to achieve that without performance penalties or undefined behaviour?
My first idea was to just use an offset and work with raw pointers on the object but that seems like it might not be defined behaviour and would also make it impossible for the compiler to detect if I'm pointing to actual fields with the correct type
You can only define a pointer to data member for a given class for actual data members of that class.
That you have a nested class type declared is no special case here: you can extract a pointer a data member of A::B and apply the pointer to data member onto the b member (of type A::B) of an A object:
#include <iostream>
struct A {
int i;
struct B{ int j; };
B b;
};
int main() {
A a{1, {42}}; // a.b.j is 42
// Declare a pointer-to-data-member of B (which
// is a nested class in A).
int A::B::*p = &A::B::j;
// Apply to an actual 'B' object to retrieve
// the data member value pointed to.
std::cout << a.b.*p; // 42
}
However if you want to apply a pointer to data member on an A object, the best you can get is a pointer to the data member b.
You could always use nested pointer to data member pointers for a nested class objects:
int main() {
A a{1, {42}}; // a.b.j is 42
A::B A::*pb = &A::b;
int A::B::*pj = &A::B::j;
std::cout << (a.*pb).*pj; // 42
}
Just for the sake of showing that what I want isn't impossible in C++ I'll provide following solution:
// Example program
#include <iostream>
#include <string>
#include <memory>
template<typename T, typename P>
class MemberPointer
{
public:
virtual P& access(T& obj) = 0;
};
template<typename T, typename P>
class SimpleMemberPointer : public MemberPointer<T, P>
{
P T::*ptr;
public:
SimpleMemberPointer(P T::*ptr): ptr(ptr){}
P& access(T& obj) override
{
return obj.*ptr;
}
using object = T;
using property = P;
};
template<typename Ptr, typename P>
class NestedMemberPointer : public MemberPointer<typename Ptr::object, P>
{
public:
using object = typename Ptr::object;
using property = P;
private:
using intermediate = typename Ptr::property;
Ptr parent;
P intermediate::*ptr;
public:
NestedMemberPointer(Ptr parent, P intermediate::*ptr): parent(parent), ptr(ptr){}
P& access(object& obj) override
{
return parent.access(obj).*ptr;
}
};
Sample usage code:
class Person
{
public:
std::string name;
struct Address{
std::string street;
}address;
};
void test(Person &p, MemberPointer<Person, std::string> &ptr)
{
std::cout << ptr.access(p) << std::endl;
}
int main()
{
Person p{"Jim", {"Street"}};
std::unique_ptr<MemberPointer<Person, std::string>> ptr = std::make_unique<SimpleMemberPointer<Person, std::string>>(&Person::name);
std::unique_ptr<MemberPointer<Person, std::string>> ptr2 = std::make_unique<NestedMemberPointer<SimpleMemberPointer<Person, Person::Address>, std::string>>(SimpleMemberPointer<Person, Person::Address>{&Person::address}, &Person::Address::street);
test(p, *ptr);
test(p, *ptr2);
}
ptr and ptr2 are variables of the same type despite refering to members in different depth, just as I want.
If executed the program prints
Jim
Street
Now the only problem with this solution is that it's not really simple and also not very performant given that it requires rather complicated variable definitions and needs polymorphism to differentiate on different paths
Suppose I have this class :
class Component1;
class Component2;
// many different Components
class Component42;
class MyClass
{
public:
MyClass(void) {};
std::list<Component1> component1List;
std::list<Component2> component2List;
// one list by component
std::list<Component42> component42List;
};
I would like to create a function with the following signature:
template<class T> void addElement(T component);
It should do the following:
if component is of type Component1, add it to Component1List
if component is of type Component2, add it to Component2List, etc.
Is it possible? What's a good way to do this?
I can obtain the same behaviour with a function like :
template<class T> void addElement(int componentType, T component);
but I'd rather not have to specify the componentType like this : it's useless information and it open the door to possible errors (if componentType doesn't represent the type of component).
std::tuple to the rescue.
changelog:
use std::decay_t
added the variadic argument form
add_component() now returns a reference to this to allow call-chaining.
#include <iostream>
#include <list>
#include <utility>
#include <type_traits>
#include <tuple>
class Component1 {};
class Component2 {};
struct Component3 {
Component3() {}
};
// many different Components
template<class...ComponentTypes>
class MyClassImpl
{
template<class Component> using list_of = std::list<Component>;
public:
using all_lists_type =
std::tuple<
list_of<ComponentTypes> ...
>;
// add a single component
template<class Component>
MyClassImpl& add_component(Component&& c)
{
list_for<Component>().push_back(std::forward<Component>(c));
return *this;
}
// add any number of components
template<class...Components>
MyClassImpl& add_components(Components&&... c)
{
using expand = int[];
void(expand { 0, (void(add_component(std::forward<Components>(c))), 0)... });
return *this;
}
template<class Component>
auto& list_for()
{
using component_type = std::decay_t<Component>;
return std::get<list_of<component_type>>(_lists);
}
template<class Component>
const auto& list_for() const
{
using component_type = std::decay_t<Component>;
return std::get<list_of<component_type>>(_lists);
}
private:
all_lists_type _lists;
};
using MyClass = MyClassImpl<Component1, Component2, Component3>;
int main()
{
MyClass c;
c.add_component(Component1());
c.add_component(Component2());
const Component3 c3;
c.add_component(c3);
c.add_components(Component1(),
Component2(),
Component3()).add_components(Component3()).add_components(Component1(),
Component2());
std::cout << c.list_for<Component1>().size() << std::endl;
return 0;
}
The most straightforward variant is to simply not use templates but to overload the addElement() function:
void addElement(Component1 element)
{
this->element1List.push_back(element);
}
void addElement(Component2 element)
{
this->element2List.push_back(element);
}
// ... etc
However, this might get tedious if you have many of these (and you don't just have addElement(), I guess). Using a macro to generate the code for each type could still do the job with reasonable effort.
If you really want to use templates, you could use a template function and specialize the template function for each type. Still, this doesn't reduce the amount of code repetition when compared with the above approach. Also, you could still reduce it using macros to generate the code.
However, there's hope for doing this in a generic way. Firstly, let's create a type that holds the list:
template<typename T>
struct ComponentContainer
{
list<T> componentList;
};
Now, the derived class just inherits from this class and uses C++ type system to locate the correct container baseclass:
class MyClass:
ComponentContainer<Component1>,
ComponentContainer<Component2>,
ComponentContainer<Component3>
{
public:
template<typename T>
void addElement(T value)
{
ComponentContainer<T>& container = *this;
container.componentList.push_back(value);
}
}
Notes here:
This uses private inheritance, which is very similar to the containment you originally used.
Even though ComponentContainer is a baseclass, it doesn't have any virtual functions and not even a virtual destructor. Yes, this is dangerous and should be documented clearly. I wouldn't add a virtual destructor though, because of the overhead it has and because it shouldn't be needed.
You could drop the intermediate container altogether and derive from list<T>, too. I didn't because it will make all of list's memberfunctions available in class MyClass (even if not publicly), which might be confusing.
You can't put the addElement() function into the base class template to avoid the template in the derived class. The simple reason is that the different baseclasses are scanned in order for a addElement() function and only then overload resolution is performed. The compiler will only find the addElement() in the first baseclass therefore.
This is a plain C++98 solution, for C++11 I'd look at the type-based tuple lookup solutions suggested by Jens and Richard.
If there are not too many classes you could go with overloading. A template-based solution could be done with type-based lookup for tuples:
class MyClass {
public:
template<typename T> void addElement(T&& x) {
auto& l = std::get<std::list<T>>(lists);
l.insert( std::forward<T>(x) );
}
private:
std::tuple< std::list<Component1>, std::list<Component2> > lists;
};
If you don't know in advance the types you will need storing when instantiating the multi-container an option is to hide the types and using type_index to keep a map of lists:
struct Container {
struct Entry {
void *list;
std::function<void *(void*)> copier;
std::function<void(void *)> deleter;
};
std::map<std::type_index, Entry> entries;
template<typename T>
std::list<T>& list() {
Entry& e = entries[std::type_index(typeid(T))];
if (!e.list) {
e.list = new std::list<T>;
e.deleter = [](void *list){ delete ((std::list<T> *)list); };
e.copier = [](void *list){ return new std::list<T>(*((std::list<T> *)list)); };
}
return *((std::list<T> *)e.list);
}
~Container() {
for (auto& i : entries) i.second.deleter(i.second.list);
}
Container(const Container& other) {
// Not exception safe... se note
for (auto& i : other.entries) {
entries[i.first] = { i.second.copier(i.second.list),
i.second.copier,
i.second.deleter };
}
};
void swap(Container& other) { std::swap(entries, other.entries); }
Container& operator=(const Container& other) {
Container(other).swap(*this);
return *this;
};
Container() { }
};
that can be used as:
Container c;
c.list<int>().push_back(10);
c.list<int>().push_back(20);
c.list<double>().push_back(3.14);
NOTE: the copy constructor as written now is not exception safe because in case a copier throws (because of an out of memory or because a copy constructor of an element inside a list throws) the already allocated lists will not be deallocated.
void addElement(Component1 component) {
componentList1.insert(component);
}
void addElement(Component2 component) {
componentList2.insert(component);
}
Note: I know similar questions to this have been asked on SO before, but I did not find them helpful or very clear.
Second note: For the scope of this project/assignment, I'm trying to avoid third party libraries, such as Boost.
I am trying to see if there is a way I can have a single vector hold multiple types, in each of its indices. For example, say I have the following code sample:
vector<something magical to hold various types> vec;
int x = 3;
string hi = "Hello World";
MyStruct s = {3, "Hi", 4.01};
vec.push_back(x);
vec.push_back(hi);
vec.push_back(s);
I've heard vector<void*> could work, but then it gets tricky with memory allocation and then there is always the possibility that certain portions in nearby memory could be unintentionally overridden if a value inserted into a certain index is larger than expected.
In my actual application, I know what possible types may be inserted into a vector, but these types do not all derive from the same super class, and there is no guarantee that all of these types will be pushed onto the vector or in what order.
Is there a way that I can safely accomplish the objective I demonstrated in my code sample?
Thank you for your time.
The objects hold by the std::vector<T> need to be of a homogenous type. If you need to put objects of different type into one vector you need somehow erase their type and make them all look similar. You could use the moral equivalent of boost::any or boost::variant<...>. The idea of boost::any is to encapsulate a type hierarchy, storing a pointer to the base but pointing to a templatized derived. A very rough and incomplete outline looks something like this:
#include <algorithm>
#include <iostream>
class any
{
private:
struct base {
virtual ~base() {}
virtual base* clone() const = 0;
};
template <typename T>
struct data: base {
data(T const& value): value_(value) {}
base* clone() const { return new data<T>(*this); }
T value_;
};
base* ptr_;
public:
template <typename T> any(T const& value): ptr_(new data<T>(value)) {}
any(any const& other): ptr_(other.ptr_->clone()) {}
any& operator= (any const& other) {
any(other).swap(*this);
return *this;
}
~any() { delete this->ptr_; }
void swap(any& other) { std::swap(this->ptr_, other.ptr_); }
template <typename T>
T& get() {
return dynamic_cast<data<T>&>(*this->ptr_).value_;
}
};
int main()
{
any a0(17);
any a1(3.14);
try { a0.get<double>(); } catch (...) {}
a0 = a1;
std::cout << a0.get<double>() << "\n";
}
As suggested you can use various forms of unions, variants, etc. Depending on what you want to do with your stored objects, external polymorphism could do exactly what you want, if you can define all necessary operations in a base class interface.
Here's an example if all we want to do is print the objects to the console:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class any_type
{
public:
virtual ~any_type() {}
virtual void print() = 0;
};
template <class T>
class concrete_type : public any_type
{
public:
concrete_type(const T& value) : value_(value)
{}
virtual void print()
{
std::cout << value_ << '\n';
}
private:
T value_;
};
int main()
{
std::vector<std::unique_ptr<any_type>> v(2);
v[0].reset(new concrete_type<int>(99));
v[1].reset(new concrete_type<std::string>("Bottles of Beer"));
for(size_t x = 0; x < 2; ++x)
{
v[x]->print();
}
return 0;
}
In order to do that, you'll definitely need a wrapper class to somehow conceal the type information of your objects from the vector.
It's probably also good to have this class throw an exception when you try to get Type-A back when you have previously stored a Type-B into it.
Here is part of the Holder class from one of my projects. You can probably start from here.
Note: due to the use of unrestricted unions, this only works in C++11. More information about this can be found here: What are Unrestricted Unions proposed in C++11?
class Holder {
public:
enum Type {
BOOL,
INT,
STRING,
// Other types you want to store into vector.
};
template<typename T>
Holder (Type type, T val);
~Holder () {
// You want to properly destroy
// union members below that have non-trivial constructors
}
operator bool () const {
if (type_ != BOOL) {
throw SomeException();
}
return impl_.bool_;
}
// Do the same for other operators
// Or maybe use templates?
private:
union Impl {
bool bool_;
int int_;
string string_;
Impl() { new(&string_) string; }
} impl_;
Type type_;
// Other stuff.
};
Lets say I have a linked list with a bunch of different data in it.
class Node
{
public:
Node* next;
AAA dataA;
BBB dataB;
CCC dataC;
};
Is there a way I make one iterator that would iterate over whatever variable I specify (rather than making three separate ones for each variable). I understand that the iterator could use templates to make it iterate over types AAA, BBB or CCC, but I don't know how I could specify which variable to return.
The best way I've found to do this is with boost bind and boost transform_iterator
First you'll need a collection of Node objects and an iterator that will traverse the collection. For brevity in my example I'll use a std::list.
#include <boost/bind.hpp>
#include <boost/iterator/transform_iterator.hpp>
using boost;
struct FunctionAAA
{
void operator() (const AAA& x)
{}
};
struct FunctionBBB
{
void operator() (const BBB& x)
{}
};
typedef std::list<Node> NodeList;
NodeList collection;
std::foreach (
make_transform_iterator (collection->begin(), bind (&Node::dataA, _1)),
make_transform_iterator (collection->end(), bind (&Node::dataA, _1)),
FunctionAAA());
std::foreach (
make_transform_iterator (collection->begin(), bind (&Node::dataB, _1)),
make_transform_iterator (collection->end(), bind (&Node::dataB, _1)),
FunctionBBB());
A possible solution is to split the iterator and the access into separate classes:
Iterator class that encapsulates the access to the data via a template argument:
template <typename Access>
class iterator
{
private:
Node *current;
public:
iterator(Node *start)
: current(start)
{
}
typename Access::typeof &operator *() const
{
return Access::access(*current);
}
bool end() const
{
return (current == NULL);
}
iterator &operator++()
{
if (current != NULL)
{
current = current->Next;
}
}
// ... other useful operators/methods
};
Classes for accessing the various data fields. THose can be used as template parameters in the iterator class:
class AccessDataA
{
public:
typedef AAA typeof;
static AAA &access(Node &node)
{
return node.dataA;
}
};
class AccessDataB
{
public:
typedef BBB typeof;
static BBB &access(Node &node)
{
return node.dataB;
}
};
class AccessDataC
{
public:
typedef CCC typeof;
static CCC &access(Node &node)
{
return node.dataC;
}
};
Example usage:
Node *start = ...;
// Loop over B:
for (iterator<AccessB> it(start); it++; !it.end())
{
// ... *it ...
}
// Loop over C:
for (iterator<AccessC> it(start); it++; !it.end())
{
// ... *it ...
}
One improvement would be to add STL compatible semantic so your list and iterator can be used in STL methods like std::for_each.
I think I've found a way to do pretty much what I want based on rstevens' suggestion. I looked up some stuff on class member pointers and was able to skip the middleman accessor class by doing this:
template <typename T>
class iterator
{
private:
Node *current;
T Node::*var;
public:
iterator()
: current(NULL), var(NULL) {}
iterator(Node *start, T Node::*var)
: current(start), var(var)
{
}
typename T &operator *() const
{
return current->*var;
}
bool end() const
{
return (current == NULL);
}
iterator &operator++()
{
if (current)
current = current->next;
return *this;
}
};
And then I modified Node to have convenience functions to make the iterators:
class Node
{
public:
Node* next;
AAA dataA;
BBB dataB;
CCC dataC;
typedef iterator<AAA> AIter;
typedef iterator<BBB> BIter;
typedef iterator<CCC> CIter;
AIter getAIter()
{
return AIter(this, &Node::dataA);
}
BIter getBIter()
{
return BIter(this, &Node::dataB);
}
CIter getCIter()
{
return CIter(this, &Node::dataC);
}
};
So now I can do this to easily iterate over each data member of my class:
for (Node::CIter iter = n1.getCIter(); !iter.end(); ++iter)
{
// tada!
}
There is no way to create a template in C++ which in itself will iterate over the members of a type. Doing so requires some help in the class either in the form of template specializations, special methods, etc ...
The template in itself would be fairly complex and would require a lot of setup work. The reason why is that given a specific type to iterate over, the template must deal with N other types. Namely the type of the members returned.
Not saying it can't be done (it can), just that this is more complex than a simple template method.
I doubt you can use templates to automatically choose the right variable to return, except by specifying three template specializations, which would be the same as defining three classes. You could however create one iterator class with three different methods to return dataA, dataB or dataC respectively (instead of operator*()).
Your question is really only a part question.
You could make an iterator adapter that acted like it iterated over a collection of AAA, but was actually iterating over a collection of Nodes. This might not be the best solution to your underlying problem, though.
I'm guessing that you have some sort of action that you want to perform on each aaa member. Suppose that this was a functor such as this.
struct DoAAAAction
{
void operator()(AAA& a);
};
It is probably easier to adapt the action to act on a Node.
template<class Action>
class DataA_ActionAdapter
{
public:
DataA_ActionAdapter( Action aa ) : a( aa ) {}
void operator()(Node& n) { a(n.dataAAA); }
private:
Action a;
};
This allows you to use standard algorithms on Node iterators.
template<class NodeIterator, class AAAAction>
void TestAAA(NodeIterator first, NodeIterator last, AAAAction aaaa)
{
std::for_each( first, last, DataA_ActionAdapter<AAAAction>( aaaa ) );
}
If I understand you correctly, you like to iterate over dataA, dataB and dataC - so this implies that AAA, BBB and CCC all share the same base type (or at least share similar characteristics). Why not simply store these in a std::vector or std::set?
Note: AAA, BBB and CCC are all derived from NodeType
class Node
{
public:
Node()
{
dataNodes.push_back(AAA());
dataNodes.push_back(BBB());
dataNodes.push_back(CCC());
}
// AAA dataA;
// BBB dataB;
// CCC dataC;
std::vector < NodeType > dataNodes;
std::vector < NodeType >::iterator begin()
{
return dataNodes.begin();
}
std::vector < NodeType >::iterator end()
{
return dataNodes.end();
}
};