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