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

Templates questions

I have some class to read and store options from a config file.

I have a design which works for the basic types. What I want to add is an array
like type. I am not sure how to define the Field Class specific template. What I
tried doesnt work.

I have included a cut down version of the code.

TIA

------example.conf
LogFile /usr/home/interlex/www/logs/access_log
OutputDir /home/interlex/www/htdocs/weblogs
PageType htm*
PageType cgi
PageType php
test_int 3467
test_float 3.143
test_double 4.54675745
test_bool true
test_bool2 false

----------code

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <stdexcept>
#include <cstdlib>
#include <locale>
#include <vector>

class FieldBase
{
public:
virtual ~FieldBase() {};
virtual void Set(const std::string &s)=0;
virtual FieldBase &operator=(const std::string &s)=0;
private:
};

template<class T>
class Field: public FieldBase
{
public:
void Set(const std::string &s);
virtual Field &operator=(const std::string &s);
T Get() const { return T(data); };
~Field() {};
private:
T data;
};

template<>
class Field<int: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atoi(s.c_str());
};

Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
int Get() const { return int(data); };
~Field() {};
private:
int data;
};

template<>
class Field<std::string>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=s;
};

Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
std::string Get() const { return std::string(data); };
~Field() {};
private:
std::string data;
};

template<>
class Field<float>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atof(s.c_str());
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
float Get() const { return float(data); };
~Field() {};
private:
float data;
};
template<>
class Field<double>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atof(s.c_str());
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
double Get() const { return double(data); };
~Field() {};
private:
double data;
};

template<>
class Field<bool>: public FieldBase
{
public:
void Set(const std::string &s)
{
std::string temp=s;
std::string::iterator i=temp.begin();
while(i!=temp.end())
{
(*i)=std::toupper(*i);
++i;
}

data=temp=="TRUE";
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
bool Get() const { return bool(data); };
~Field() {};
private:
bool data;
};
#if 0
template<>
class Field<std::vector<std::string: public FieldBase
{
public:
void Set(const std::string &s)
{
data.push_back(s);
}

Field &operator=(const std::string &s)
{
Set(s);
return *this;
}

std::vector<std::stringGet() const {return data;};
~Field() {};
private:
std::vector<std::stringdata;
}
#endif

class Config
{
public:
virtual ~Config();
void parse(void);

template<class T>
T Get(const std::string &f) const
{
Fields_t::const_iterator i=fields_.find(f);
if(i!=fields_.end())
{
try
{
const Field<T&ptr=dynamic_cast<Field<T&>(*i->second);
return ptr.Get();
}
catch(...)
{
throw;
}
}
throw std::runtime_error("Config field " + f + " does not exist");
}

template<class T>
void AddField(const std::string &fieldname, bool required=true)
{
fields_[fieldname]=new Field<T>();
}

protected:
Config(const std::string &file);

private:
typedef std::map<std::string, FieldBase *Fields_t;
void trim_(std::string &l);
Fields_t fields_;
std::string filename_;
static const char comment_char_='#';
};

class ExampleConfig : public Config
{
public:
ExampleConfig(const std::string &file);
private:
};

Config::Config(const std::string &file)
: filename_(file)
{
}

Config::~Config()
{
for(Fields_t::iterator i=fields_.begin(); i!=fields_.end(); i++)
{
delete (i->second);
}
}

void Config::parse(void)
{
std::ifstream in;
std::string keyword;
std::string value;
std::string line;

in.open(filename_.c_str());
if(!in.is_open())
{
throw std::runtime_error("Could not open file: " + filename_);
}

while(getline(in, line))
{
trim_(line);
if(line[0]==comment_char_ || line.empty())
{
continue;
}
keyword=line.substr(0, line.find_first_of(" \t"));
line.erase(0, keyword.length());
value=line.substr(line.find_first_not_of(" \t"));

FieldBase *ptr=fields_[keyword];
if(ptr)
{
ptr->Set(value);
}
}
}

void Config::trim_(std::string &l)
{
const char *white_space=" \t";
l.erase(0, l.find_first_not_of(white_space));
l.erase(l.find_last_not_of(white_space)+1);
}
ExampleConfig::ExampleConfig(const std::string &file)
:Config(file)
{
AddField<std::string>("OutputDir");
AddField<std::string>("LogFile");
AddField<std::string>("PageType");
// I want to be able to do something like below
// AddField<std::vector<std::string("PageType");
AddField<float>("test_float");
AddField<double>("test_double");
AddField<bool>("test_bool");
AddField<bool>("test_bool2");
AddField<int>("test_int");

parse();
}

int main(int argc, char *argv[])
{
try
{
ExampleConfig config("example.conf");

std::cout << config.Get<std::string>("LogFile") << std::endl;
std::cout << config.Get<std::string>("OutputDir") << std::endl;
std::cout << config.Get<std::string>("PageType") << std::endl;
// I want to be able to do something like below
// std::cout << config.Get<std::vector<std::string("PageType")[0] << std::endl;
std::cout << config.Get<int>("test_int") << std::endl;
std::cout << config.Get<float>("test_float") << std::endl;
std::cout << config.Get<double>("test_double") << std::endl;
std::cout << config.Get<bool>("test_bool") << std::endl;
std::cout << config.Get<bool>("test_bool2") << std::endl;
std::cout << config.Get<std::string>("HideURL") << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

--

Adrian

Think you know a language? Post to comp.lang... and find out!
Nov 6 '06 #1
3 1253

Adrian wrote:
I have some class to read and store options from a config file.

I have a design which works for the basic types. What I want to add is an array
like type. I am not sure how to define the Field Class specific template. What I
tried doesnt work.

I have included a cut down version of the code.

TIA

------example.conf
LogFile /usr/home/interlex/www/logs/access_log
OutputDir /home/interlex/www/htdocs/weblogs
PageType htm*
PageType cgi
PageType php
test_int 3467
test_float 3.143
test_double 4.54675745
test_bool true
test_bool2 false

----------code

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <stdexcept>
#include <cstdlib>
#include <locale>
#include <vector>

class FieldBase
{
public:
virtual ~FieldBase() {};
virtual void Set(const std::string &s)=0;
virtual FieldBase &operator=(const std::string &s)=0;
private:
};

template<class T>
class Field: public FieldBase
{
public:
void Set(const std::string &s);
virtual Field &operator=(const std::string &s);
T Get() const { return T(data); };
~Field() {};
private:
T data;
};

template<>
class Field<int: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atoi(s.c_str());
};

Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
int Get() const { return int(data); };
~Field() {};
private:
int data;
};

template<>
class Field<std::string>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=s;
};

Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
std::string Get() const { return std::string(data); };
~Field() {};
private:
std::string data;
};

template<>
class Field<float>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atof(s.c_str());
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
float Get() const { return float(data); };
~Field() {};
private:
float data;
};
template<>
class Field<double>: public FieldBase
{
public:
void Set(const std::string &s)
{
data=std::atof(s.c_str());
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
double Get() const { return double(data); };
~Field() {};
private:
double data;
};

template<>
class Field<bool>: public FieldBase
{
public:
void Set(const std::string &s)
{
std::string temp=s;
std::string::iterator i=temp.begin();
while(i!=temp.end())
{
(*i)=std::toupper(*i);
++i;
}

data=temp=="TRUE";
};
Field &operator=(const std::string &s)
{
Set(s);
return *this;
};
bool Get() const { return bool(data); };
~Field() {};
private:
bool data;
};
#if 0
template<>
class Field<std::vector<std::string: public FieldBase
{
public:
void Set(const std::string &s)
{
data.push_back(s);
}

Field &operator=(const std::string &s)
{
Set(s);
return *this;
}

std::vector<std::stringGet() const {return data;};
~Field() {};
private:
std::vector<std::stringdata;
}
#endif

class Config
{
public:
virtual ~Config();
void parse(void);

template<class T>
T Get(const std::string &f) const
{
Fields_t::const_iterator i=fields_.find(f);
if(i!=fields_.end())
{
try
{
const Field<T&ptr=dynamic_cast<Field<T&>(*i->second);
return ptr.Get();
}
catch(...)
{
throw;
}
}
throw std::runtime_error("Config field " + f + " does not exist");
}

template<class T>
void AddField(const std::string &fieldname, bool required=true)
{
fields_[fieldname]=new Field<T>();
}

protected:
Config(const std::string &file);

private:
typedef std::map<std::string, FieldBase *Fields_t;
void trim_(std::string &l);
Fields_t fields_;
std::string filename_;
static const char comment_char_='#';
};

class ExampleConfig : public Config
{
public:
ExampleConfig(const std::string &file);
private:
};

Config::Config(const std::string &file)
: filename_(file)
{
}

Config::~Config()
{
for(Fields_t::iterator i=fields_.begin(); i!=fields_.end(); i++)
{
delete (i->second);
}
}

void Config::parse(void)
{
std::ifstream in;
std::string keyword;
std::string value;
std::string line;

in.open(filename_.c_str());
if(!in.is_open())
{
throw std::runtime_error("Could not open file: " + filename_);
}

while(getline(in, line))
{
trim_(line);
if(line[0]==comment_char_ || line.empty())
{
continue;
}
keyword=line.substr(0, line.find_first_of(" \t"));
line.erase(0, keyword.length());
value=line.substr(line.find_first_not_of(" \t"));

FieldBase *ptr=fields_[keyword];
if(ptr)
{
ptr->Set(value);
}
}
}

void Config::trim_(std::string &l)
{
const char *white_space=" \t";
l.erase(0, l.find_first_not_of(white_space));
l.erase(l.find_last_not_of(white_space)+1);
}
ExampleConfig::ExampleConfig(const std::string &file)
:Config(file)
{
AddField<std::string>("OutputDir");
AddField<std::string>("LogFile");
AddField<std::string>("PageType");
// I want to be able to do something like below
// AddField<std::vector<std::string("PageType");
AddField<float>("test_float");
AddField<double>("test_double");
AddField<bool>("test_bool");
AddField<bool>("test_bool2");
AddField<int>("test_int");

parse();
}

int main(int argc, char *argv[])
{
try
{
ExampleConfig config("example.conf");

std::cout << config.Get<std::string>("LogFile") << std::endl;
std::cout << config.Get<std::string>("OutputDir") << std::endl;
std::cout << config.Get<std::string>("PageType") << std::endl;
// I want to be able to do something like below
// std::cout << config.Get<std::vector<std::string("PageType")[0] << std::endl;
std::cout << config.Get<int>("test_int") << std::endl;
std::cout << config.Get<float>("test_float") << std::endl;
std::cout << config.Get<double>("test_double") << std::endl;
std::cout << config.Get<bool>("test_bool") << std::endl;
std::cout << config.Get<bool>("test_bool2") << std::endl;
std::cout << config.Get<std::string>("HideURL") << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

--

Adrian

Think you know a language? Post to comp.lang... and find out!
the code compiles fine with VS 2005. What compiler are you using ?

Nov 6 '06 #2
am******@gmail.com wrote:
the code compiles fine with VS 2005. What compiler are you using ?
gcc 3.4.2

Its the bits that are commented out that wont compile well.
--

Adrian

Think you know a language? Post to comp.lang... and find out!
Nov 6 '06 #3

Adrian wrote:
am******@gmail.com wrote:
the code compiles fine with VS 2005. What compiler are you using ?
gcc 3.4.2

Its the bits that are commented out that wont compile well.
--

Adrian

Think you know a language? Post to comp.lang... and find out!
We use gcc 3.4.3, I find the template support highly lacking compared
to the latest Visual Studio. I have had similar experiences of template
code working in Visual Studio and not gcc/g++. Maybe the latest gcc
(4.x) resolves some of these issues.

Nov 7 '06 #4

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

Similar topics

4
by: franky.backeljauw | last post by:
Hello, I have a problem with using a copy constructor to convert an object of a templated class to object of another templated class. Let me first include the code (my question is below): ...
4
by: Dave Theese | last post by:
Hello all, I'm trying to get a grasp of the difference between specializing a function template and overloading it. The example below has a primary template, a specialization and an overload. ...
5
by: Tom Alsberg | last post by:
Hi there... I'm recently trying to get a bit acquainted with XML Schemas and XSL. Now, I have a few questions about XSL stylesheets and templates: * Is there a way to "enter" a child element...
2
by: Kimmo | last post by:
Folks, I have a XML document that has been put together from a "dynamic part" (generated somehow during runtime) and a "static part" (read from a control file). Basically the document looks like...
8
by: bartek | last post by:
Hello, I've been toying around with expression templates recently while writing a simple static lexical analyser, hence I have some questions which keep bothering me... The expression objects...
2
by: Niklas Norrthon | last post by:
I want to share a technique I recently have found to be useful to get around some obstacles that data protection can raise. Consider the following class: // foo.h #ifndef H_FOO #define H_FOO...
11
by: Elpoca | last post by:
Hi: What rules govern the inlining of templated functions and templated class methods? It has always been my understanding that both templated functions and templated class methods were...
25
by: Ted | last post by:
I'm putting the posts that follow here (hopefully they will follow here!) because they were rejected in comp.lang.c++.moderated. It behooves anyone reading them to first read the the thread of the...
2
by: sarathy | last post by:
Hi all, I need a small clarification reg. Templates and Polymorphism. I believe templates is really a good feature, which can be used to implement generic functions and classes. But i doubt...
6
by: pleexed | last post by:
hello, this is my first post in a newsgroup, i hope i do everything right :) first of all, i am sure there have been a lot of "are templates slow?" questions around, but i think what i would...
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: 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: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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: 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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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...

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.