473,241 Members | 1,601 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,241 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 1551
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: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

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.