Hello, I've made a templated class Option (a child of the abstract base
class OptionBase) that stores an option name (in the form someoption=) and
the value belonging to that option. The value is of the type the object is
instantiated with. In my test program I have Option<std::string> and
Option<long>. Here's the code for OptionBase and Option along with a small
helper function. In the code are comments describing my problem, look
closely at the read_option() and convert() functions in the Option class.
#ifndef OPTION_HPP
#define OPTION_HPP
#include <stdexcept>
#include <string>
#include <typeinfo>
static 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());
if(str == starts_with)
return true;
return false;
}
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);
std::string str = s.substr(m_name.length(), s.length());
if(str.empty())
throw std::runtime_error("Option lacks value.");
/* Problem: Will try to convert std::string to std::string
which will lead to "Iron Gual Dye" becoming just "Iron". */
T tmp = convert(str);
set_value(tmp);
}
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:
T convert(const std::string& s)
{
/* Here I want to simply return s if(typeid(T) == typeid(std::string)
but return (T)s doesn't compile when this class is instantiated
with type long (I'm using long and std::string in my test program).
*/
stringstream ss;
ss << s;
T out;
if(!(ss >> out))
throw runtime_error("Conversion not possible.");
return out;
}
T m_value;
};
#endif /* #ifndef OPTION_HPP */
So the problem is convert(). When I have instantiated my object with
std::string and I call read_option() on that object it will call convert()
and convert() will convert a string containing spaces to a substring up to
the first space. Iron Gual Dye becomes Iron for example. How should I
prevent this from happening? If I have instantiated with std::string I don't
want to call convert (because it messes up strings with spaces) but I have
to because of set_value().
Hope you understand what I mean...I can provide a complete and compilable
example exhibiting the problem should anyone want me to.
/ Eric 4 3584
Eric Lilja wrote: template<typename T> class Option : public OptionBase { public: Option(const std::string& name) : OptionBase(name) {}
virtual void read_option(const std::string& s) {
[snip]
/* Problem: Will try to convert std::string to std::string which will lead to "Iron Gual Dye" becoming just "Iron". */ T tmp = convert(str);
set_value(tmp); }
[snip]
private: T convert(const std::string& s) { /* Here I want to simply return s if(typeid(T) ==
typeid(std::string) but return (T)s doesn't compile when this class is
instantiated with type long (I'm using long and std::string in my test
program). */
stringstream ss; ss << s;
T out;
if(!(ss >> out)) throw runtime_error("Conversion not possible.");
return out; }
T m_value; };
#endif /* #ifndef OPTION_HPP */
So the problem is convert(). When I have instantiated my object with std::string and I call read_option() on that object it will call
convert() and convert() will convert a string containing spaces to a substring
up to the first space. Iron Gual Dye becomes Iron for example. How should I
prevent this from happening? If I have instantiated with std::string
I don't want to call convert (because it messes up strings with spaces) but I
have to because of set_value().
Hope you understand what I mean...I can provide a complete and
compilable example exhibiting the problem should anyone want me to.
/ Eric
You can create a specialization for Option<std::string> that does not
read from the string stream.
Hope this helps,
-shez-
"Shezan Baig" wrote: Eric Lilja wrote: template<typename T> class Option : public OptionBase { public: Option(const std::string& name) : OptionBase(name) {}
virtual void read_option(const std::string& s) {
[snip]
/* Problem: Will try to convert std::string to std::string which will lead to "Iron Gual Dye" becoming just "Iron". */ T tmp = convert(str);
set_value(tmp); }
[snip]
private: T convert(const std::string& s) { /* Here I want to simply return s if(typeid(T) == typeid(std::string) but return (T)s doesn't compile when this class is instantiated with type long (I'm using long and std::string in my test program). */
stringstream ss; ss << s;
T out;
if(!(ss >> out)) throw runtime_error("Conversion not possible.");
return out; }
T m_value; };
#endif /* #ifndef OPTION_HPP */
So the problem is convert(). When I have instantiated my object with std::string and I call read_option() on that object it will call convert() and convert() will convert a string containing spaces to a substring up to the first space. Iron Gual Dye becomes Iron for example. How should I
prevent this from happening? If I have instantiated with std::string I don't want to call convert (because it messes up strings with spaces) but I have to because of set_value().
Hope you understand what I mean...I can provide a complete and compilable example exhibiting the problem should anyone want me to.
/ Eric
You can create a specialization for Option<std::string> that does not read from the string stream.
Hope this helps, -shez-
Thanks for your reply. I tried moving the convert() function outside the
class and made a specialization for it for std::string but it always calls
the "wrong" convert. The code:
template<typename T>
T convert(const std::string& s, T)
{
stringstream ss;
ss << s;
T out;
if(!(ss >> out))
throw runtime_error("Conversion not possible.");
return out;
}
template<typename T>
std::string convert(const std::string& s, std::string)
{
return s;
}
But maybe that's not what you meant? My template skills are a bit weak I
must say =/
/ Eric
"Eric Lilja" wrote: "Shezan Baig" wrote: Eric Lilja wrote: template<typename T> class Option : public OptionBase { public: Option(const std::string& name) : OptionBase(name) {}
virtual void read_option(const std::string& s) {
[snip]
/* Problem: Will try to convert std::string to std::string which will lead to "Iron Gual Dye" becoming just "Iron". */ T tmp = convert(str);
set_value(tmp); }
[snip]
private: T convert(const std::string& s) { /* Here I want to simply return s if(typeid(T) == typeid(std::string) but return (T)s doesn't compile when this class is instantiated with type long (I'm using long and std::string in my test program). */
stringstream ss; ss << s;
T out;
if(!(ss >> out)) throw runtime_error("Conversion not possible.");
return out; }
T m_value; };
#endif /* #ifndef OPTION_HPP */
So the problem is convert(). When I have instantiated my object with std::string and I call read_option() on that object it will call convert() and convert() will convert a string containing spaces to a substring up to the first space. Iron Gual Dye becomes Iron for example. How should I
prevent this from happening? If I have instantiated with std::string I don't want to call convert (because it messes up strings with spaces) but I have to because of set_value().
Hope you understand what I mean...I can provide a complete and compilable example exhibiting the problem should anyone want me to.
/ Eric
You can create a specialization for Option<std::string> that does not read from the string stream.
Hope this helps, -shez-
Thanks for your reply. I tried moving the convert() function outside the class and made a specialization for it for std::string but it always calls the "wrong" convert. The code: template<typename T> T convert(const std::string& s, T) { stringstream ss; ss << s;
T out;
if(!(ss >> out)) throw runtime_error("Conversion not possible.");
return out; }
template<typename T> std::string convert(const std::string& s, std::string) { return s; }
But maybe that's not what you meant? My template skills are a bit weak I must say =/
/ Eric
I solved it, here it is with the convert() function as a stand-alone
function:
template<typename T1, typename T2>
T2 convert(const T1& a, const T2&)
{
stringstream ss;
ss << a;
T2 out;
if(!(ss >> out))
throw runtime_error("Conversion not possible.");
return out;
}
template<>
std::string convert(const std::string& s, const std::string&)
{
return s;
}
Now, should I (can I?) make convert a member of the class Option? And can I
loose the second argument (it's after all not used in the function)?
/ Eric
Eric Lilja wrote: I solved it, here it is with the convert() function as a stand-alone function: template<typename T1, typename T2> T2 convert(const T1& a, const T2&) { stringstream ss; ss << a;
T2 out;
if(!(ss >> out)) throw runtime_error("Conversion not possible.");
return out; }
template<> std::string convert(const std::string& s, const std::string&) { return s; }
Now, should I (can I?) make convert a member of the class Option? And
can I loose the second argument (it's after all not used in the function)?
/ Eric
You don't need to second argument. In the option class, declare it
like this:
template<typename RETURN_TYPE>
RETURN_TYPE convert(const std::string& s);
Outside the class, provide two definitions for this function, one
generic and the other specialized for std::string:
template <typename TYPE>
template <typename RETURN_TYPE>
RETURN_TYPE Option<TYPE>::convert(const std::string& s)
{
// ...
}
template <typename TYPE>
template <>
std::string Option<TYPE>::convert<std::string>(const std::string& s)
{
// ...
}
When you call the convert function, you call it like this:
convert<TYPE>(s);
So, if 'TYPE' is 'std::string', it will call the specialised version.
Hope this helps,
-shez- This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Arvid Andersson |
last post by:
Hello, I need to convert a string to a number, but the string can
contain +,-,* and / as well as parenthesis. For example, if I have the
string "30/(6+9)" I would like a function that returned the...
|
by: Dave |
last post by:
Hello all,
Quoting from page 24 of "The Boost Graph Library; User Guide and Reference
Manual":
"It turns out that by the contravariance subtyping rule, the parameter type
in the derived...
|
by: Gerry Abbott |
last post by:
Hi All,
Im trying to use thie combination but have not had success. Below is the
function
It tried the following
myriskLevel(2,2)
myrisklevel(0,0,2)
and the ismissing(Three) alwasy...
|
by: Edward Diener |
last post by:
In C++ an overridden virtual function in a derived class must have the exact
same signature of the function which is overridden in the base class, except
for the return type which may return a...
|
by: Ian Bicking |
last post by:
I got a puzzler for y'all. I want to allow the editing of functions
in-place. I won't go into the reason (it's for HTConsole --
http://blog.ianbicking.org/introducing-htconsole.html), except that...
|
by: mosesdinakaran |
last post by:
Hi everybody,
Today I faced a problem where I am very confused and I could not
solve it and I am posting here....
My question is
Is is possible to return a value to a particular function
...
|
by: FAQ server |
last post by:
-----------------------------------------------------------------------
FAQ Topic - Why does 1+1 equal 11? or How do I convert a string to a number?...
|
by: Robert Dufour |
last post by:
I am trying to sort the membership list of the membership provider for
ASP.NET
the code has retrieved the list and now we need to sort it by a parameter if
it was passed. So in C# the code is....
|
by: FAQ server |
last post by:
-----------------------------------------------------------------------
FAQ Topic - Why does 1+1 equal 11? or How do I convert a
string to a number?...
|
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...
|
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: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
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...
| |