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

Any way to get rid of the cast when calling get_value()?

Hello, I have a std::vector storing pointers to an abstract base class
OptionBase. OptionBase is not templated but I am deriving a template class
called Option from OptionBase. The class Option has a public member function
called get_value() that is not present in the class OptionBase. My problem
is that when calling get_value() I have to cast to Option<some_type>* and I
was wondering if I can somehow remove the cast so I dont have to remember
exatly what type Option is instantiated with.

Some code to clarify:

typedef Option<string> StringOption;
typedef Option<long> LongOption;

vector<OptionBase*> options(8);

options[0] = new StringOption("Name=");
options[1] = new StringOption("Process=");
options[2] = new LongOption("Level=");
options[3] = new StringOption("Technique=");
options[4] = new StringOption("Knowledge=");
options[5] = new StringOption("Device=");
options[6] = new StringOption("Primary components=");
options[7] = new StringOption("Build components=");

/* Is there a way to remove these casts so I dont have to remember
exactly what type I used to instantiate Option at each element? */
((StringOption*)options[0])->get_value(), /* name */
((StringOption*)options[1])->get_value(), /* process */
((LongOption*)options[2])->get_value(), /* level */

The class definitions:
class OptionBase
{
public:
OptionBase(const std::string& name)
:
m_name(name),
m_not_set(true) {}

virtual ~OptionBase() {}

virtual void read_option(const std::string&) = 0;

const std::string get_name() const
{
return m_name;
}

protected:
std::string m_name;
bool m_not_set;
};

template<typename T>
class Option : public OptionBase
{
public:
Option(const std::string& name)
:
OptionBase(name) {}

virtual void read_option(const std::string& s)
{
if(!starts_with(s, m_name))
throw std::runtime_error(std::string("Didn't find option ") +
m_name);

/* TODO: Turn this into a call to copy_all_past() function. */
std::string str = s.substr(m_name.length(), s.length());

if(str.empty())
throw std::runtime_error("Option lacks value.");

set_value(convert<T>(str));
}

T get_value() const
{
if(m_not_set)
throw std::runtime_error("Called get_value() when no value had been
set.");

return m_value;
}

void set_value(const T& value)
{
m_value = value;
m_not_set = false;
}

private:
bool starts_with(const std::string& s, const std::string& starts_with)
{
if(s.length() < starts_with.length())
return false;

std::string str = s.substr(0, starts_with.length());

return (str == starts_with);
}

template<typename T>
T convert(const std::string& a)
{
std::istringstream ss(a);

T out;

if(!(ss >> out))
throw runtime_error("Conversion not possible.");

return out;
}

/* We need this specialization so we don't try to convert
a std::string to a std::string. Doing so will loose
all but the first "word" in string containing spaces. */
template<>
std::string convert(const std::string& s)
{
return s;
}

T m_value;
};

Thanks for reading and replying...hope my question made sense

/ Eric
Jul 23 '05 #1
6 1559
Sep
Couldn't you make get_value() into a pure virtual function in
OptionBase and rely on the vtable to call the correct function? Or do
you not want to incur the extra overhead?

Jul 23 '05 #2

"Sep" wrote:
Couldn't you make get_value() into a pure virtual function in
OptionBase and rely on the vtable to call the correct function? Or do
you not want to incur the extra overhead?


Thanks for your reply, Sep. I'm not concerned about virtual function
overhead just not sure how the declaration of get_value() would look like in
the OptionBase class, i.e., what should its return type be?

/ Eric
Jul 23 '05 #3
Sep
Sorry, I was a bit hasty in typing that up and forgot that template
functions cannot be virtual.

Jul 23 '05 #4
Sep
I had thought at first that get_value() had to be a template class but
then thankfully remembered the relaxation of type rule.

To make get_value() into a virtual function, just define it with an
arbitrary non-void type in OptionBase as a pure virtual then override
it in Options with return type T. The return-type of overridden
virtual functions is allowed to differ, making this allowed. Now the
correct function will be called polymorphically when calling
get_value() through a pointer to OptionBase.

Jul 23 '05 #5
Sep
Nope, that wasn't correct either. Having a bit of a bad day in the
thinking department.

Jul 23 '05 #6
"Eric Lilja" <er*************@yahoo.com> wrote in message
news:d0**********@news.island.liu.se...
Hello, I have a std::vector storing pointers to an abstract base class
OptionBase. OptionBase is not templated but I am deriving a template class
called Option from OptionBase. The class Option has a public member function called get_value() that is not present in the class OptionBase. My problem
is that when calling get_value() I have to cast to Option<some_type>* and I was wondering if I can somehow remove the cast so I dont have to remember
exatly what type Option is instantiated with.

Some code to clarify:

typedef Option<string> StringOption;
typedef Option<long> LongOption;

vector<OptionBase*> options(8);

options[0] = new StringOption("Name=");
options[1] = new StringOption("Process=");
options[2] = new LongOption("Level=");
options[3] = new StringOption("Technique=");
options[4] = new StringOption("Knowledge=");
options[5] = new StringOption("Device=");
options[6] = new StringOption("Primary components=");
options[7] = new StringOption("Build components=");

/* Is there a way to remove these casts so I dont have to remember
exactly what type I used to instantiate Option at each element? */
((StringOption*)options[0])->get_value(), /* name */
((StringOption*)options[1])->get_value(), /* process */
((LongOption*)options[2])->get_value(), /* level */

[...]

When possible, the preferred way to downcast to a subclass from a base is
dynamic_cast, because it will perform a runtime check to see if the cast
succeeded (correct type) or failed (wrong type). The C-style casts that you
are using won't do that.

To answer your question, you could have multiple member functions:

virtual long OptionBase::get_long_value();
virtual std::string OptionBase::get_string_value();

They could either throw exceptions if the type doesn't match, or attempt to
convert between the types to satisfy the request. You'd still need to know
the "correct" or "compatible" type(s) before calling the members, though.
This approach would be fine if the number of option types was small and
unchanging, but it might get ugly if more and more types had to be added
later.

--
David Hilsee
Jul 23 '05 #7

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

Similar topics

18
by: Graham Nicholls | last post by:
Hi. I'm having some fun with numbers. I've extraced an image sizes from a jpeg file img_x,img_y=image.getsize() then I'm trying to use those sizes to scale the image, but because python...
10
by: Tony Johansson | last post by:
Hello Experts!! This class template and main works perfectly fine. I have this class template called Handle that has a pointer declared as T* body; As you can see I have a reference counter in...
5
by: Nick Flandry | last post by:
I'm running into an Invalid Cast Exception on an ASP.NET application that runs fine in my development environment (Win2K server running IIS 5) and a test environment (also Win2K server running IIS...
4
by: Mike Cooper | last post by:
There is something about inherited classes I evidently don't know... I wrote the following class: Class Class1 inherits System.Windows.Forms.DataGridTextBoxColumn End Class There is...
4
by: JackBlack | last post by:
Hi, all! Need a little help tracking down a runtime error problem. I'm getting this error: "Unable to cast object of type 'myStruct' to type 'myStruct'... but the two types are identical! I...
5
by: taumuon | last post by:
I've got an object, Person, that supports IEquatable<Person>. It implements bool Equals(Person obj) as well as overriding bool Equals(object obj) I've got a container type that holds a member...
18
by: Felix Kater | last post by:
I haven't been thinking about it for years but recently I've stumbled on the fact that 'casting' is actually doing (at least) two different things: On the one hand 'casting' means: 'Change...
6
by: alan | last post by:
I'm creating a sort-of "wrapper" class which (partly) acts like a variable. Something like: template<class t> class cell{ t curval; public: /*public for debugging only - will be private in...
20
by: raylopez99 | last post by:
Inspired by Chapter 8 of Albahari's excellent C#3.0 in a Nutshell (this book is amazing, you must get it if you have to buy but one C# book) as well as Appendix A of Jon Skeet's book, I am going...
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
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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...
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...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new...

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.