473,396 Members | 1,765 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.

Hiding template in non-template class

Hello,

I did read the FAQ on template(*), since I could not find an answer
to my current issue I am posting here. I have tried to summarize my
issue in the following code (**).
Basically I am trying to hide the `complexity` of template from the
user interface. If you look at the code DataSet should be the object
that my user manipulate. Unfortunately by doing so the object returned
by DataSet::Get is a FloatingPt, so without the virtual keyword, the
DataSet does not correctly hide the templated class.
Basically I am asking on design to resolve this issue, how one
usually hide template class in a non-templated class without making my
FloatingPt class virtual ? If this is detailed in the C++ FAQ please
give me keywords associated with this problem.

Thanks a bunch !
Mathieu
(*)
http://www.parashift.com/c++-faq-lite/templates.html

(**)
#include <iostream>
#include <vector>

class FloatingPt {
public:
/*virtual*/void Type() { std::cout << "FloatingPt" << std::endl; }
};
class Float : public FloatingPt {
public:
void Type() { std::cout << "Float" << std::endl; }
float f;
};
class Double : public FloatingPt {
public:
void Type() { std::cout << "Double" << std::endl; }
double d;
};

template <typename T>
class TDataSet
{
public:
TDataSet(int n = 10):Internal(n) {}
T &Get(int i) { return Internal[i]; }
private:
std::vector<TInternal;
};

class DataSet
{
public:
DataSet(bool t = false):isfloat(t) {}
FloatingPt &Get(int i) {
if( isfloat )
return FloatDS.Get(i);
else
return DoubleDS.Get(i);
}
private:
bool isfloat;
TDataSet<Float FloatDS;
TDataSet<DoubleDoubleDS;
};

int main(int , char *[])
{
DataSet ds;
ds.Get(0).Type();

return 0;
}

Sep 10 '06 #1
7 3431

What are you actually trying to achieve by hiding the template nature
of the DataSet class? Is this just because you prefer the sintax

DataSet ds(true|false);

over

DataSet<float|doubleds;

? The design you are currently using is bad, because you have to
include two members inside your class each of one type and thus making
your structure larger in order to be able to store values according to
a parameter in constructor of the class. Templates exist for the very
sake of allowing the same functionality to be applied to different
types without rewriting the code or storing variables of multiple
types. Why exactly do you prefer defining the type used through the
constructor function argument instead of through the template argument
as it is ment to be?
mathieu wrote:
Hello,

I did read the FAQ on template(*), since I could not find an answer
to my current issue I am posting here. I have tried to summarize my
issue in the following code (**).
Basically I am trying to hide the `complexity` of template from the
user interface. If you look at the code DataSet should be the object
that my user manipulate. Unfortunately by doing so the object returned
by DataSet::Get is a FloatingPt, so without the virtual keyword, the
DataSet does not correctly hide the templated class.
Basically I am asking on design to resolve this issue, how one
usually hide template class in a non-templated class without making my
FloatingPt class virtual ? If this is detailed in the C++ FAQ please
give me keywords associated with this problem.

Thanks a bunch !
Mathieu
(*)
http://www.parashift.com/c++-faq-lite/templates.html

(**)
#include <iostream>
#include <vector>

class FloatingPt {
public:
/*virtual*/void Type() { std::cout << "FloatingPt" << std::endl; }
};
class Float : public FloatingPt {
public:
void Type() { std::cout << "Float" << std::endl; }
float f;
};
class Double : public FloatingPt {
public:
void Type() { std::cout << "Double" << std::endl; }
double d;
};

template <typename T>
class TDataSet
{
public:
TDataSet(int n = 10):Internal(n) {}
T &Get(int i) { return Internal[i]; }
private:
std::vector<TInternal;
};

class DataSet
{
public:
DataSet(bool t = false):isfloat(t) {}
FloatingPt &Get(int i) {
if( isfloat )
return FloatDS.Get(i);
else
return DoubleDS.Get(i);
}
private:
bool isfloat;
TDataSet<Float FloatDS;
TDataSet<DoubleDoubleDS;
};

int main(int , char *[])
{
DataSet ds;
ds.Get(0).Type();

return 0;
}
Sep 10 '06 #2
If your only goal is that the Type() function should print out the type
member variable you could solve this writing a template class, but
write it's specializations for types float and double:

template<typename T>
class DataSet {
T myfloat;
void Type() {std::cout << "Some other type" << std:endl;}
};

template<>
class DataSet<float{
float myfloat;
void Type() {std::cout << "float type" << std::endl;}
};

template<>
class DataSet<double{
double myfloat;
void Type() {std::cout << "double type" << std::endl;}
};

ivan.le...@gmail.com wrote:
What are you actually trying to achieve by hiding the template nature
of the DataSet class? Is this just because you prefer the sintax

DataSet ds(true|false);

over

DataSet<float|doubleds;

? The design you are currently using is bad, because you have to
include two members inside your class each of one type and thus making
your structure larger in order to be able to store values according to
a parameter in constructor of the class. Templates exist for the very
sake of allowing the same functionality to be applied to different
types without rewriting the code or storing variables of multiple
types. Why exactly do you prefer defining the type used through the
constructor function argument instead of through the template argument
as it is ment to be?
mathieu wrote:
Hello,

I did read the FAQ on template(*), since I could not find an answer
to my current issue I am posting here. I have tried to summarize my
issue in the following code (**).
Basically I am trying to hide the `complexity` of template from the
user interface. If you look at the code DataSet should be the object
that my user manipulate. Unfortunately by doing so the object returned
by DataSet::Get is a FloatingPt, so without the virtual keyword, the
DataSet does not correctly hide the templated class.
Basically I am asking on design to resolve this issue, how one
usually hide template class in a non-templated class without making my
FloatingPt class virtual ? If this is detailed in the C++ FAQ please
give me keywords associated with this problem.

Thanks a bunch !
Mathieu
(*)
http://www.parashift.com/c++-faq-lite/templates.html

(**)
#include <iostream>
#include <vector>

class FloatingPt {
public:
/*virtual*/void Type() { std::cout << "FloatingPt" << std::endl; }
};
class Float : public FloatingPt {
public:
void Type() { std::cout << "Float" << std::endl; }
float f;
};
class Double : public FloatingPt {
public:
void Type() { std::cout << "Double" << std::endl; }
double d;
};

template <typename T>
class TDataSet
{
public:
TDataSet(int n = 10):Internal(n) {}
T &Get(int i) { return Internal[i]; }
private:
std::vector<TInternal;
};

class DataSet
{
public:
DataSet(bool t = false):isfloat(t) {}
FloatingPt &Get(int i) {
if( isfloat )
return FloatDS.Get(i);
else
return DoubleDS.Get(i);
}
private:
bool isfloat;
TDataSet<Float FloatDS;
TDataSet<DoubleDoubleDS;
};

int main(int , char *[])
{
DataSet ds;
ds.Get(0).Type();

return 0;
}
Sep 10 '06 #3
[sorry for top posting]

I have tried to describing my issue in as little code as possible.
Apparently with too simple code. Instead of DataSet of my previous try
to see a a Factory Method approach.
Ex: User is reading files with set of floating points value: either
float or double. In the end the file reader will construct a DataSet,
the user should not have to know the floating type contains in the file
to instanciate the reader.
Another problem I am facing is to contruct a python interface to my
library (using swig). In which case I cannot have any template
classes...

Hopefully this is clearer now
Mathieu

iv********@gmail.com wrote:
What are you actually trying to achieve by hiding the template nature
of the DataSet class? Is this just because you prefer the sintax

DataSet ds(true|false);

over

DataSet<float|doubleds;

? The design you are currently using is bad, because you have to
include two members inside your class each of one type and thus making
your structure larger in order to be able to store values according to
a parameter in constructor of the class. Templates exist for the very
sake of allowing the same functionality to be applied to different
types without rewriting the code or storing variables of multiple
types. Why exactly do you prefer defining the type used through the
constructor function argument instead of through the template argument
as it is ment to be?
mathieu wrote:
Hello,

I did read the FAQ on template(*), since I could not find an answer
to my current issue I am posting here. I have tried to summarize my
issue in the following code (**).
Basically I am trying to hide the `complexity` of template from the
user interface. If you look at the code DataSet should be the object
that my user manipulate. Unfortunately by doing so the object returned
by DataSet::Get is a FloatingPt, so without the virtual keyword, the
DataSet does not correctly hide the templated class.
Basically I am asking on design to resolve this issue, how one
usually hide template class in a non-templated class without making my
FloatingPt class virtual ? If this is detailed in the C++ FAQ please
give me keywords associated with this problem.

Thanks a bunch !
Mathieu
(*)
http://www.parashift.com/c++-faq-lite/templates.html

(**)
#include <iostream>
#include <vector>

class FloatingPt {
public:
/*virtual*/void Type() { std::cout << "FloatingPt" << std::endl; }
};
class Float : public FloatingPt {
public:
void Type() { std::cout << "Float" << std::endl; }
float f;
};
class Double : public FloatingPt {
public:
void Type() { std::cout << "Double" << std::endl; }
double d;
};

template <typename T>
class TDataSet
{
public:
TDataSet(int n = 10):Internal(n) {}
T &Get(int i) { return Internal[i]; }
private:
std::vector<TInternal;
};

class DataSet
{
public:
DataSet(bool t = false):isfloat(t) {}
FloatingPt &Get(int i) {
if( isfloat )
return FloatDS.Get(i);
else
return DoubleDS.Get(i);
}
private:
bool isfloat;
TDataSet<Float FloatDS;
TDataSet<DoubleDoubleDS;
};

int main(int , char *[])
{
DataSet ds;
ds.Get(0).Type();

return 0;
}
Sep 10 '06 #4
[Sorry for top posting]

Ivan,

Thanks again for trying to address my issue. But I am having a hard
time understanding your proposed solution. DataSet is still a template
class in your exemple, right ? How would you design a 'Reader' class
that take as input an istream (containing either float or double value)
and returning a DataSet ?
I would like to keep the template code for the development but propose
a non templated interface for the user. I am sure there are some
pattern for doing it properly.

Thanks
Mathieu

iv********@gmail.com wrote:
If your only goal is that the Type() function should print out the type
member variable you could solve this writing a template class, but
write it's specializations for types float and double:

template<typename T>
class DataSet {
T myfloat;
void Type() {std::cout << "Some other type" << std:endl;}
};

template<>
class DataSet<float{
float myfloat;
void Type() {std::cout << "float type" << std::endl;}
};

template<>
class DataSet<double{
double myfloat;
void Type() {std::cout << "double type" << std::endl;}
};

ivan.le...@gmail.com wrote:
What are you actually trying to achieve by hiding the template nature
of the DataSet class? Is this just because you prefer the sintax

DataSet ds(true|false);

over

DataSet<float|doubleds;

? The design you are currently using is bad, because you have to
include two members inside your class each of one type and thus making
your structure larger in order to be able to store values according to
a parameter in constructor of the class. Templates exist for the very
sake of allowing the same functionality to be applied to different
types without rewriting the code or storing variables of multiple
types. Why exactly do you prefer defining the type used through the
constructor function argument instead of through the template argument
as it is ment to be?
mathieu wrote:
Hello,
>
I did read the FAQ on template(*), since I could not find an answer
to my current issue I am posting here. I have tried to summarize my
issue in the following code (**).
Basically I am trying to hide the `complexity` of template from the
user interface. If you look at the code DataSet should be the object
that my user manipulate. Unfortunately by doing so the object returned
by DataSet::Get is a FloatingPt, so without the virtual keyword, the
DataSet does not correctly hide the templated class.
Basically I am asking on design to resolve this issue, how one
usually hide template class in a non-templated class without making my
FloatingPt class virtual ? If this is detailed in the C++ FAQ please
give me keywords associated with this problem.
>
Thanks a bunch !
Mathieu
>
>
(*)
http://www.parashift.com/c++-faq-lite/templates.html
>
(**)
#include <iostream>
#include <vector>
>
class FloatingPt {
public:
/*virtual*/void Type() { std::cout << "FloatingPt" << std::endl; }
};
class Float : public FloatingPt {
public:
void Type() { std::cout << "Float" << std::endl; }
float f;
};
class Double : public FloatingPt {
public:
void Type() { std::cout << "Double" << std::endl; }
double d;
};
>
template <typename T>
class TDataSet
{
public:
TDataSet(int n = 10):Internal(n) {}
T &Get(int i) { return Internal[i]; }
private:
std::vector<TInternal;
};
>
class DataSet
{
public:
DataSet(bool t = false):isfloat(t) {}
FloatingPt &Get(int i) {
if( isfloat )
return FloatDS.Get(i);
else
return DoubleDS.Get(i);
}
private:
bool isfloat;
TDataSet<Float FloatDS;
TDataSet<DoubleDoubleDS;
};
>
int main(int , char *[])
{
DataSet ds;
ds.Get(0).Type();
>
return 0;
}
Sep 10 '06 #5
I have tried to describing my issue in as little code as possible.
Apparently with too simple code. Instead of DataSet of my previous try
to see a a Factory Method approach.
Ex: User is reading files with set of floating points value: either
float or double. In the end the file reader will construct a DataSet,
the user should not have to know the floating type contains in the file
to instanciate the reader.
Another problem I am facing is to contruct a python interface to my
library (using swig). In which case I cannot have any template
classes...
So if I understand right, you want the user to be able to create an
instance of this reader class without specifying which type of floating
points it is going to read. Instead the internal functions of the class
would find out what kind of numbers there are in the file and read and
store them appropriately for the user. Did I get it right?

Now I assume you want the two structures specialized for floats and
doubles in order to save space in memory and save floats instead of
doubles when the numbers in file are of smaller accuracy. This can be
achieved without two specialized templates. Instead just write two
dedicated classes and an abstract one to define the interface. However,
this design (with no templates) has many flaws. Let me illustrate with
these three classes:

//abstract interface
class FP {
virtual bool isDouble() { return false; }
void set(double d) { }
double get() { }
//you have to use double so you don't loose
//accuracy in FP_Double
};

//specialized classes
class FP_Float {
float f;
bool isDouble() { return false; }
void set(double d) { this->f = d; }
double get() { return this->f; }
};

class FP_Double {
double d;
bool isDouble() { return true; }
void set(double d) { this->d = d; }
double get() { return this->d; }
};

//reader
class Reader {
//stores pointers to FP structures
vector<FP*data;

void read(const char *filename) {
//do whatever you want to read a number...
//...when you get the number:
FP *newFP;
if (is_single_precision)
newFP = new FP_Float;
if (is_double_precision) {
newFP = new FP_Double;
//assign value
newFP->set(number_read);
data.push_back(newFP);
}
};

Now here come the problems:
1. One could think we saved 4 bytes per variable since we stored floats
instead of doubles. But that is not entirely true - that's because we
allocated the FP_Double and FP_Float classes dinamically and stored
pointers to them (which are of size 4 bytes on a 32-bit architecture)
in the vector instead. This means we allocated additional 4 bytes per
each number!
2. We had to use a single interface for both classes (always using
doubles in the get/set functions) in order not to loose accuracy in the
FP_Double class.

These are exactly the problems which templates were designed to solve.
Unfortunately template types are resolved at compile-time, but your
kind of problem requires determining the storage type of numbers at
run-time. This is the source of your problem. In fact there is no way
to safely avoid template classes when you want to have a single storage
of "variable" size. Here variable is of course meant "at compile time".
An unsafe (and error-prone) way is to manually allocate enough memory
to store the data in and type-cast the pointer to it according to your
knowledge about what kind of data there should be. The vector (and all
the rest from the standard template library) were designed as template
classes in order to remove this unsafeness. But if you want to try it I
can show you a simple example. It will not implement a resizible data
structure (like vector) but instead just show the principle.

class Reader
{
bool isDoublePrecision;
void *data;

Reader(): isDoublePrecision(false), data(NULL) {}
~Reader() { if(data) delete data; }

void readFile(const char *filename) {
//1.somehow determine the type and number of floats in the file
//2. allocate the space needed
if (is_single_precision) {
isDoublePrecision = false;
data = new float[number_of_floats];
//read floats into data array
}
if (is_double_precision) {
isDoublePrecision = true;
data = new double[number_of_floats];
//read doubles into data array
}
}

double getData(int index) {
if (isDoublePrecision)
return ((double*)data)[index];
else
return ((float*)data)[index];
}
};

But always remember to properly cast the pointer any time you might be
using it.

greets,
Ivan Leben

Sep 10 '06 #6
.... and another version using type-casted pointer to a vector class

class Reader
{
bool isDoublePrecision;
void *data;

Reader(): isDoublePrecision(false), data(NULL) {}

void readFile(const char *filename) {
//1.somehow determine the type and number of floats in the file
//2. allocate the space needed
if (is_single_precision) {
isDoublePrecision = false;
data = new vector<float>;
//read floats into data
}
if (is_double_precision) {
isDoublePrecision = true;
data = new vector<double>;
//read doubles into data
}
}

double getData(int index) {
if (isDoublePrecision)
return ((vector<double>*)data)->at(index);
else
return ((vector<float>*)data)->at(index);
}

};

Note that these reader classes are in fact just a simplification of all
your code in the first post. It just shows you don't have to use
inheritance and templates to implement all this. Just use a type-casted
pointer to something and that's all the trick there is. However, I must
warn again that this is not a nice C++ practice and it's very unsafe
and error-prone, but I think it's the only way you can get rid of
template classes and still allocate only 1 data storage instead of 1
for each data type.

Sep 10 '06 #7

iv********@gmail.com wrote:
....
store them appropriately for the user. Did I get it right?
yes :)
Now I assume you want the two structures specialized for floats and
doubles in order to save space in memory and save floats instead of
doubles when the numbers in file are of smaller accuracy. This can be
achieved without two specialized templates. Instead just write two
dedicated classes and an abstract one to define the interface. However,
this design (with no templates) has many flaws. Let me illustrate with
these three classes:
template were useful to avoid duplicating code, right ?
//abstract interface
class FP {
....
};

//specialized classes
class FP_Float {
....
};

class FP_Double {
....
};

//reader
class Reader {
//stores pointers to FP structures
vector<FP*data;

void read(const char *filename) {
//do whatever you want to read a number...
//...when you get the number:
FP *newFP;
if (is_single_precision)
newFP = new FP_Float;
if (is_double_precision) {
newFP = new FP_Double;
//assign value
newFP->set(number_read);
data.push_back(newFP);
}
};

Now here come the problems:
1. One could think we saved 4 bytes per variable since we stored floats
instead of doubles. But that is not entirely true - that's because we
allocated the FP_Double and FP_Float classes dinamically and stored
pointers to them (which are of size 4 bytes on a 32-bit architecture)
in the vector instead. This means we allocated additional 4 bytes per
each number!
Actually adding dynamic binding (virtual) to FP adds 4 more bytes to
the object size.
2. We had to use a single interface for both classes (always using
doubles in the get/set functions) in order not to loose accuracy in the
FP_Double class.
So in general with two objects, you rely on the fact you can cast one
to the other. And use the 'more precise' one to define your interface.
These are exactly the problems which templates were designed to solve.
Unfortunately template types are resolved at compile-time, but your
kind of problem requires determining the storage type of numbers at
run-time. This is the source of your problem. In fact there is no way
to safely avoid template classes when you want to have a single storage
of "variable" size. Here variable is of course meant "at compile time".
An unsafe (and error-prone) way is to manually allocate enough memory
to store the data in and type-cast the pointer to it according to your
knowledge about what kind of data there should be. The vector (and all
the rest from the standard template library) were designed as template
classes in order to remove this unsafeness. But if you want to try it I
can show you a simple example. It will not implement a resizible data
structure (like vector) but instead just show the principle.

class Reader
{
....
};

But always remember to properly cast the pointer any time you might be
using it.
I just came accross the Iterator and Visitor pattern. It looks to me
that I can avoid the problem by never exposing the internal type (in my
case: float or double). Let me study those.

Thanks anyway !
Mathieu

Sep 10 '06 #8

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

Similar topics

8
by: Fabian | last post by:
Is there a way to hiode the horizontal (but NOT the vertical) scrollbar? -- -- Fabian Visit my website often and for long periods! http://www.lajzar.co.uk
38
by: | last post by:
I have a script... ----- <SCRIPT language="JavaScript" type="text/javascript"> <!-- function makeArray() { for (i = 0; i<makeArray.arguments.length; i++) this = makeArray.arguments; } ...
11
by: Kevin | last post by:
I've got a timer on my MDI parent form. If there's no mouse movement for a set number of minutes, the Visible property of all open forms is set to False and the Log On form is displayed. I could do...
3
by: dd | last post by:
Hi, I have some code that hides all Flash objects on a page. It's working fine on IE and Gecko but doesn't work on Safari. There are no errors (shown in the console) when it runs on Safari, and...
0
by: King007 | last post by:
Hello, I have two modes of running my application, one is UI mode and the other is non UI mode, I have a flag to check whether the operator is in UI or Non- ui mode., In non ui mode i try not to...
12
by: Ste | last post by:
Hi there, I've got a website with a list of Frequently Asked Questions, so there's a question and answer in a long list down the page. Can anyone recommend a simple script that would allow me...
11
by: JJ297 | last post by:
I want to hide the Pin field below in my repeater. How do I do this? <asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1"> <ItemTemplate> <tr> <td><font...
0
by: Samuel Bayer | last post by:
Jonathan Gardner wrote: At the risk of prolonging this thread, I'll add my own personal insight. I've spent a decent amount of time programming in Java, and the overhead of assigning a...
7
by: dweeti | last post by:
Hi, I am trying to display the child element in the DOM, while hiding the parent using JS and CSS, however I cannot find a way to do this. So for example: <body> <div id="Parent"> <div...
27
by: matt | last post by:
Hello group, I'm trying to become familiar with the information hiding design rules, and I have a lot (3) of questions for all you experts. AFAIK, a generic module has 2 files: ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
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...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
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,...

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.