473,385 Members | 1,409 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,385 software developers and data experts.

Avoiding rtti

I'm interested in computational physics and have defined an abstract base
class to represent a simulation. Now I want to develop a GUI for setting
the member data of classes derived from my base class.

I've approached this problem by creating a class named Interface with an
overloaded member function named addParameter():

class Interface {
public:
void addParameter( int& param );
void addParameter( double& param );
// etc.
};

Simulations call addParameter() on their data and the GUI works by keeping
pointers to the data. These pointers (along with other data to be displayed
by the GUI such as the name of the parameter, etc.) are stored in a
template struct named Parameter derived from a base class called
ParameterBase:

class ParameterBase {
virtual ~ParameterBase() {};
};

template<typename T>
struct Parameter : public ParameterBase {
T* data;
};

The GUI keeps track of these Parameters by managing a vector of
ParameterBase pointers, but this requires rtti. Can anyone suggest an
approach that doesn't?

I've also tried writing the Interface this way

class Interface {
public:
template<typename T>
void addParameter( T& param );
private:
template<typename T>
vector<T*>& parameters();
};

template<typename T>
vector<T*>& Interface::parameters()
{
static vector<T*> vec;
return vec;
}

template<typename T>
void Interface::addParameter( T& x )
{
parameters<T>().push_back( &x );
}

This avoids the problems associated with storing base class pointers, but
requires a way to keep track of what types addParameter() has been called
on. Furthermore I would still have to write code like

for( all the elements of parameters<int>() )
do_something

for( all the elements of parameters<double>() )
do_something

All comments are welcome.

Daniel
Jul 22 '05 #1
4 1707
Daniel Mitchell <da*********@mail.utexas.edu> wrote in
news:cc**********@geraldo.cc.utexas.edu:
The GUI keeps track of these Parameters by managing a vector of
ParameterBase pointers, but this requires rtti. Can anyone suggest an
approach that doesn't?


The visitor pattern.

#include <iostream>
#include <vector>

// --- Visitor ABS.

template <typename T> class Parameter;

struct Visitor {
virtual ~Visitor() { }
virtual void visit(Parameter<float>&) = 0;
virtual void visit(Parameter<double>&) = 0;
// ...
};

// --- Parameter base

struct ParameterBase {
virtual ~ParameterBase() {};
virtual void applyVisitor(Visitor&) = 0;
};

// --- Parameter implementation

template<typename T>
class Parameter : public ParameterBase {
T data;
public:
Parameter(T const& value) : data(value) { }
virtual void applyVisitor(Visitor& v) { v.visit(*this); }
};

// --- Visitor implementation

template <typename OStream>
class Printer : public Visitor {
OStream& out;
public:
Printer(OStream& out) : out(out) { }
virtual void visit(Parameter<float>& p) {
out << 'f' << ':' << p.data;
}
virtual void visit(Parameter<double>& p) {
out << 'd' << ':' << p.data;
}
// ...
};

// ---

int main() {
using namespace std;

vector<ParameterBase*> v;
v.push_back(new Parameter<float>(1.2f));
v.push_back(new Parameter<double>(0.1));

Printer<std::ostream> p(std::cout);
std::vector<ParameterBase*>::iterator it = v.begin();
for (; it != v.end(); ++it) {
(*it)->applyVisitor(p);
std::cout << ' ';
}
std::cout << '\n';

return 0;
}

Jul 22 '05 #2
On Fri, 2 Jul 2004 11:03:06 +0000 (UTC), bartek
<sp******************@o2.pl> wrote:

This won't compile:
#include <iostream>
#include <vector>

// --- Visitor ABS.

template <typename T> class Parameter;

struct Visitor {
virtual ~Visitor() { }
virtual void visit(Parameter<float>&) = 0;
virtual void visit(Parameter<double>&) = 0;
// ...
};

// --- Parameter base

struct ParameterBase {
virtual ~ParameterBase() {};
virtual void applyVisitor(Visitor&) = 0;
};

// --- Parameter implementation

template<typename T>
class Parameter : public ParameterBase {
T data;
public:
Parameter(T const& value) : data(value) { }
virtual void applyVisitor(Visitor& v) { v.visit(*this); }
};

// --- Visitor implementation

template <typename OStream>
class Printer : public Visitor {
OStream& out;
public:
Printer(OStream& out) : out(out) { }
virtual void visit(Parameter<float>& p) {
out << 'f' << ':' << p.data; ^^^^^^
p.data is not accessible to Visitor here because it is a private
member of Parameter.

Either make "data" public, or use a getter function, or make Visitor a
friend of Parameter, and it should compile.
}
virtual void visit(Parameter<double>& p) {
out << 'd' << ':' << p.data;
}
// ...
};

// ---

int main() {
using namespace std;

vector<ParameterBase*> v;
v.push_back(new Parameter<float>(1.2f));
v.push_back(new Parameter<double>(0.1));

Printer<std::ostream> p(std::cout);
std::vector<ParameterBase*>::iterator it = v.begin();
for (; it != v.end(); ++it) {
(*it)->applyVisitor(p);
std::cout << ' ';
}
std::cout << '\n';

return 0;
}

Who gets to delete the Parameter* that were created with "new"?

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #3
Bob Hairgrove <wo**************@to.know> wrote in
news:hg********************************@4ax.com:
On Fri, 2 Jul 2004 11:03:06 +0000 (UTC), bartek
<sp******************@o2.pl> wrote:

This won't compile:
#include <iostream>
#include <vector>

// --- Visitor ABS.

template <typename T> class Parameter;

struct Visitor {
virtual ~Visitor() { }
virtual void visit(Parameter<float>&) = 0;
virtual void visit(Parameter<double>&) = 0;
// ...
};

// --- Parameter base

struct ParameterBase {
virtual ~ParameterBase() {};
virtual void applyVisitor(Visitor&) = 0;
};

// --- Parameter implementation

template<typename T>
class Parameter : public ParameterBase {
T data;
public:
Parameter(T const& value) : data(value) { }
virtual void applyVisitor(Visitor& v) { v.visit(*this); }
};

// --- Visitor implementation

template <typename OStream>
class Printer : public Visitor {
OStream& out;
public:
Printer(OStream& out) : out(out) { }
virtual void visit(Parameter<float>& p) {
out << 'f' << ':' << p.data; ^^^^^^
p.data is not accessible to Visitor here because it is a private
member of Parameter.

Either make "data" public, or use a getter function, or make Visitor a
friend of Parameter, and it should compile.


You're absolutely right. Thanks for pointing it out.
}
virtual void visit(Parameter<double>& p) {
out << 'd' << ':' << p.data;
}
// ...
};

// ---

int main() {
using namespace std;

vector<ParameterBase*> v;
v.push_back(new Parameter<float>(1.2f));
v.push_back(new Parameter<double>(0.1));

Printer<std::ostream> p(std::cout);
std::vector<ParameterBase*>::iterator it = v.begin();
for (; it != v.end(); ++it) {
(*it)->applyVisitor(p);
std::cout << ' ';
}
std::cout << '\n';

return 0;
}

Who gets to delete the Parameter* that were created with "new"?


Whoever writes real code will know what to do, I guess.

Perhaps I should have noted, that this code is just an approximate sample
of how a basic visitor is usually implemented. Not how to write proper
C++ code. I just hope that it wouldn't be really difficult for a person
who knows C++ to find it out.

Cheers.
Jul 22 '05 #4
> This avoids the problems associated with storing base class pointers, but
requires a way to keep track of what types addParameter() has been called
on. Furthermore I would still have to write code like

for( all the elements of parameters<int>() )
do_something

for( all the elements of parameters<double>() )
do_something

All comments are welcome.

Daniel

Why you didn't overload the member "do_something"? In this case you
would have:

for (forall elm in container)
{
elm.do_something (...);
}

Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Rick | last post by:
Hi, I wrote a few classes recently and am writing a small GC implementation for C++. I will be implementing my own gc_ptr type maintain a list where I'll store pointers to allocated memory. I...
2
by: shishir | last post by:
Please consider the following //file test.cpp #include <iostream> int main() { int x; try { throw x;
6
by: Kleidemos | last post by:
If I implement a simple RTTI system, more simple than C++ RTTI system for my program and this system is plus or minus: #define DEF_RTTI_BASE(name) virtual inline const char *Name(){ return...
9
by: Agoston Bejo | last post by:
Hello there, I would like to know what overheads there are to think of when using RTTI. I understand that enabling RTTI increases the sizes of the classes, but not the objects themselves. This...
2
by: denny | last post by:
Hey all, I know that dynamic_cast<> takes some time, but , for instance, is there a memoy cost associated in with it? Does it have to maintain a table in memory, thus bloating the runtime ram...
3
by: Steven T. Hatton | last post by:
I'm trying to work out a design for dynamically determining file types, and for generating new files of a given type. I'm curious to know what others think of my current strategy. Is it "so...
5
by: dotNeter | last post by:
I'm studying the RTTI, and my current work is concern for how to get the self-defined type at runtime, that's exactly what the RTTI does. I mean, in my application, I built several self-defined...
2
by: Chameleon | last post by:
I know than dynamic_cast check string name of derived to base class and if one of them match, return the pointer of that object or else zero. I suppose, I dynamic_cast instead of strings, checks...
3
by: n.torrey.pines | last post by:
Hi I work with a nested tree-like data structure template (that happens to be a tuple of vectors of tuples of trees of something, with different tuple elements having different types) I need...
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: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.