473,569 Members | 3,043 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

is there a simple solution to this template problem?

Hi everyone,

The idea is quite simple: generate a container with random values in
it. For that, I decided to create a class that I called
RandomContainer that inherits from a container (with default value
std::vector<T>) . To handle the different ways that the values are
randomized, I created a traits class. The problem that I have, is that
the function randomize() within the traits class takes different
parameters depending on the type (bool takes none, int takes one
parameter and double takes two parameters). Is there a way to make
this function randomize() a generic function? How do I handle the
different parameters? The code is as follows:

// no definition for generic type
template <typename T>
class AlleleTraits {};

// partial specialization for boolean type
template<>
struct AlleleTraits<bo ol{

static bool randomize() {
return flip(0.5);
}
};

// partial specialization for integer type
template<>
struct AlleleTraits<in t{

static int randomize(int k) {
return rnd(0, k-1);
}
};

// partial specialization for double type
template<>
struct AlleleTraits<do uble{

static double randomize(doubl e low, double high) {
return rnd(low, high);
}
};

// RandomContainer class
template <
typename T,
class Container = std::vector<T>,
class TTraits = AlleleTraits<T>
>
struct RandomContainer : public Container {

typedef typename Container::iter ator iterator;

RandomContainer (size_t size) : Container(size) {}
void initialize(int k) {
for(int i=0; i<this->size(); ++i) {
this->operator[](i) = TTraits::random ize(k);
}
}

void print() {
for(int i=0; i<this->size(); ++i) {
cout<<" "<<this->at(i);
}
}
};
// main.cxx
....
RandomContainer <inttest(10);
test.initialize (6);
test.print();
....

prints:

1 4 3 1 5 1 4 0 3 1

This is fine because the function randomize(int) was defined within
RandomContainer . If I try to do the same with double or bool I have
compiler errors because of course, those functions are not defined
within the traits class.

Thank you,



Jun 24 '07 #1
7 2009
I don't think there is any good way in C++ to do exactly what you want
(have the function take a varying number of arguments based on a
template). However you can obtain nearly the same result by requiring
each of the AlleleTraits to have an internal "initialize r" object.
Then instead of passing in different numbers of parameters you can
pass in different initializers ( see code below ).

---------------

// no definition for generic type
template <typename T>
class AlleleTraits {};

// partial specialization for boolean type
template<>
struct AlleleTraits<bo ol{

struct initializer {};

static bool randomize(const initializer& val) {
return flip(0.5);
}

};
// partial specialization for integer type
template<>
struct AlleleTraits<in t{

typedef int initializer;

static int randomize(const initializer& k) {
return rnd(0, k-1);
}

};

// partial specialization for double type
template<>
struct AlleleTraits<do uble{

struct initializer
{
initializer(dou ble l, double h) { low = l; high = h; }
double low, high;
};

static double randomize(const initializer& init) {
return rnd(low, high);
}

};

// RandomContainer class
template <
typename T,
class Container = vector<T>,
class TTraits = AlleleTraits<T

struct RandomContainer : public Container {

typedef typename Container::iter ator iterator;
typedef typename AlleleTraits<T> ::initializer initializer;

RandomContainer (size_t size) : Container(size) {}

void initialize(cons t initializer& v) {
for(unsigned int i=0; i<this->size(); ++i) {
this->operator[](i) = TTraits::random ize(v);
}
}

void print() {
for(unsigned int i=0; i<this->size(); ++i) {
cout<<" "<<this->at(i);
}
}
};

// main.cxx

.....
RandomContainer <booltest(6);
test.initialize (AlleleTraits<b ool>::initializ er());
test.print();

RandomContainer <inttest2(6);
test2.initializ e(AlleleTraits< int>::initializ er(2));
test2.print();

RandomContainer <doubletest3(6) ;
test3.initializ e(AlleleTraits< double>::initia lizer(.2, .5));
test3.print();
.....

Hopefully that's more or less what your are looking for,

Mark

Jun 25 '07 #2
On Jun 24, 10:01 pm, mark.te...@gmai l.com wrote:
I don't think there is any good way in C++ to do exactly what you want
(have the function take a varying number of arguments based on a
template). However you can obtain nearly the same result by requiring
each of the AlleleTraits to have an internal "initialize r" object.
Then instead of passing in different numbers of parameters you can
pass in different initializers ( see code below ).

---------------

// no definition for generic type
template <typename T>
class AlleleTraits {};

// partial specialization for boolean type
template<>
struct AlleleTraits<bo ol{

struct initializer {};

static bool randomize(const initializer& val) {
return flip(0.5);
}

};

// partial specialization for integer type
template<>
struct AlleleTraits<in t{

typedef int initializer;

static int randomize(const initializer& k) {
return rnd(0, k-1);
}

};

// partial specialization for double type
template<>
struct AlleleTraits<do uble{

struct initializer
{
initializer(dou ble l, double h) { low = l; high = h; }
double low, high;
};

static double randomize(const initializer& init) {
return rnd(low, high);
}

};

// RandomContainer class
template <
typename T,
class Container = vector<T>,
class TTraits = AlleleTraits<T

struct RandomContainer : public Container {

typedef typename Container::iter ator iterator;
typedef typename AlleleTraits<T> ::initializer initializer;

RandomContainer (size_t size) : Container(size) {}

void initialize(cons t initializer& v) {
for(unsigned int i=0; i<this->size(); ++i) {
this->operator[](i) = TTraits::random ize(v);
}
}

void print() {
for(unsigned int i=0; i<this->size(); ++i) {
cout<<" "<<this->at(i);
}
}

};

// main.cxx

....
RandomContainer <booltest(6);
test.initialize (AlleleTraits<b ool>::initializ er());
test.print();

RandomContainer <inttest2(6);
test2.initializ e(AlleleTraits< int>::initializ er(2));
test2.print();

RandomContainer <doubletest3(6) ;
test3.initializ e(AlleleTraits< double>::initia lizer(.2, .5));
test3.print();
....

Hopefully that's more or less what your are looking for,

Mark

Mark, thanks for replying, I like your solution. This is what I came
up with before reading yours:

template <typename T>
class AlleleTraits {}
;

template<>
struct AlleleTraits<bo ol{

static bool randomize() {
return flip(0.5);
}
};

template<>
struct AlleleTraits<in t{

static int low_;
static int high_;

static int randomize() {
return rnd(low_, high_-1);
}
static int cardinality() {
return high_ - low_;
}
static void setLimits(int low, int high) {
low_ = low;
high_ = high;
}
};
int AlleleTraits<in t>::low_;
int AlleleTraits<in t>::high_ = 2;

template<>
struct AlleleTraits<do uble{

static double low_;
static double high_;

static double randomize() {
return rnd(AlleleTrait s<double>::low_ ,
AlleleTraits<do uble>::high_);
}
static void setLimits(doubl e low, double high) {
low_ = low;
high_ = high;
}
static double range() {
return high_ - low_;
}

};
double AlleleTraits<do uble>::low_;
double AlleleTraits<do uble>::high_ = 1;

template <
typename T,
class Container = std::vector<T>,
class TTraits = AlleleTraits<T>
>
struct RandomContainer : public Container {

typedef T ValueType;
typedef typename Container::iter ator Iterator;

RandomContainer (size_t size) : Container(size) {}
static void setLimits(T low, T high) {
AlleleTraits<T> ::setLimits(low ,high);
}

void initialize() {
for(int i=0; i<this->size(); ++i) {
this->operator[](i) = TTraits::random ize();
}
}

void print() {
for(int i=0; i<this->size(); ++i) {
cout<<" "<<this->at(i);
}
}
};

// main.cxx
// ...
RandomContainer <booltest0(10 );
test0.initializ e();
test0.print();

RandomContainer <inttest(10);
RandomContainer <int>::setLimit s(3,9);
test.initialize ();
test.print();

RandomContainer <doubletest2(10 );
RandomContainer <double>::setLi mits(0.22,9.333 );
test2.initializ e();
test2.print();
// ...
0 1 0 0 0 1 1 0 1 0
5 4 5 4 8 7 3 3 7 7
0.368547 2.43343 1.47059 7.54846 1.64782 3.87381 1.40278 1.21157
9.3232 2.20898

However, I will change it so the RandomContainer definition takes
another template parameter and I won't provide a default value for it
(I think the behavior of the container has to be something that the
client has to specify in a single statement and completely). As a
matter of fact, your solution could enter here quite nicely:

template <
typename T,
TTraits::initia lizer,
class Container = std::vector<T>,
class TTraits = AlleleTraits<T>
>
struct RandomContainer : public Container {
//...
};

The thing is that this code has to be written by the client, and I
want to make it as easy as possible. So, I don't know yet how to
implement this because I don't want the client to write code like the
following:

typedef RandomContainer <double, AlleleTraits<do uble>::initiali zer>
doubleContainer ;

I will definitely keep the static variables within the AlleleTraits
classes though. Maybe writing a macro that expands the previous code
would be a solution to make the code simpler to the client? I don't
know. Any other ideas?



Jun 25 '07 #3
On Jun 25, 1:18 am, aaragon <alejandro.ara. ..@gmail.comwro te:
The thing is that this code has to be written by the client, and I
want to make it as easy as possible. So, I don't know yet how to
implement this because I don't want the client to write code like the
following:

typedef RandomContainer <double, AlleleTraits<do uble>::initiali zer>
doubleContainer ;
Do you mind if they have to write code like this?

typedef RandomContainer <double, AlleleTraitsdou bleContainer;

If not, you can declare RandomContainer like this:
template<typena me _T, template<typena meclass _Traits>
class RandomContainer
{
private:
typedef typename _Traits<_T>::in itializer _Initializer;
};

Jun 25 '07 #4
Zachary Turner wrote:
>
Do you mind if they have to write code like this?

typedef RandomContainer <double, AlleleTraitsdou bleContainer;

If not, you can declare RandomContainer like this:
template<typena me _T, template<typena meclass _Traits>
class RandomContainer
{
private:
typedef typename _Traits<_T>::in itializer _Initializer;
};
Actually, you can't declare it as such. You have generated ill-formed
code, as many of your identifiers (_T, _Initializer, and _Traits) are
reserved to the implementation.

Jun 25 '07 #5
On Jun 25, 11:33 am, red floyd <no.s...@here.d udewrote:
Zachary Turner wrote:
Do you mind if they have to write code like this?
typedef RandomContainer <double, AlleleTraitsdou bleContainer;
If not, you can declare RandomContainer like this:
template<typena me _T, template<typena meclass _Traits>
class RandomContainer
{
private:
typedef typename _Traits<_T>::in itializer _Initializer;
};

Actually, you can't declare it as such. You have generated ill-formed
code, as many of your identifiers (_T, _Initializer, and _Traits) are
reserved to the implementation.
It is true. Besides, I don't think there is a way to include doubles
in constant expressions, so no matter how I try, I won't be able to
initialize everything with a single type definition. I guess the best
approach so far is the one using static functions to set the limits
of the container after its type definition. Any other ideas?

Jun 25 '07 #6
On Jun 25, 12:34 pm, aaragon <alejandro.ara. ..@gmail.comwro te:
template<typena me _T, template<typena meclass _Traits>
class RandomContainer
{
private:
typedef typename _Traits<_T>::in itializer _Initializer;
};
Actually, you can't declare it as such. You have generated ill-formed
code, as many of your identifiers (_T, _Initializer, and _Traits) are
reserved to the implementation.

It is true. Besides, I don't think there is a way to include doubles
in constant expressions, so no matter how I try, I won't be able to
initialize everything with a single type definition. I guess the best
approach so far is the one using static functions to set the limits
of the container after its type definition. Any other ideas?- Hide quoted text -
Ok, so remove the underscores and change the name to whatever you
want. Can you give an example that illustrates what you won't be able
to accomplish using the above approach? I'm not sure I follow.

Jun 25 '07 #7
On Jun 25, 1:39 pm, Zachary Turner <divisorthe...@ gmail.comwrote:
On Jun 25, 12:34 pm, aaragon <alejandro.ara. ..@gmail.comwro te:
template<typena me _T, template<typena meclass _Traits>
class RandomContainer
{
private:
typedef typename _Traits<_T>::in itializer _Initializer;
};
Actually, you can't declare it as such. You have generated ill-formed
code, as many of your identifiers (_T, _Initializer, and _Traits) are
reserved to the implementation.
It is true. Besides, I don't think there is a way to include doubles
in constant expressions, so no matter how I try, I won't be able to
initialize everything with a single type definition. I guess the best
approach so far is the one using static functions to set the limits
of the container after its type definition. Any other ideas?- Hide quoted text -

Ok, so remove the underscores and change the name to whatever you
want. Can you give an example that illustrates what you won't be able
to accomplish using the above approach? I'm not sure I follow.
Well, I was hoping the user to declare everything in the container
with a single line, something like the following:

typedef RandomContainer <double, 0.2, 9.9doubleContai ner;
typedef RandomContainer <int, 1, 8intContainer;
typedef RandomContainer <boolboolContai ner;

but I don't think something like this is possible because you cannot
use double values in constant expressions. Also, this type definition
is a part of a bigger type definition so I must be able to do this at
compile time. That's why I think the only way to do it is with static
functions to set the limits of the container:

typedef RandomContainer <doubledoubleCo ntainer;
typedef RandomContainer <intintContaine r;
typedef RandomContainer <boolboolContai ner;

doubleContainer ::setLimits(0.2 ,9.9);
intContainer::s etLimits(1,8);

If there is a better way to accomplish the same thing, please let me
know.



Jun 27 '07 #8

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

Similar topics

13
34357
by: Noah Spitzer-Williams | last post by:
Hello guys, I would like to do something seemingly simple: find out if an element in an array that is passed to my function exists. I used to think I could just do: if (arr) ... However, if this element's value happens to be 0, the conditional will return false, even though the element actually exists. Any ideas? Can you check if the...
7
1587
by: Leon | last post by:
I'm having a bit of a template-problem, and I was wondering if you guru's know what I'm doing wrong here... I want to create a Vertex class that supports a toPoint() method. Now, in my case there are 2 ways of calculating toPoint(), and I want to be able to choose (at compile time) this method in a flexible way. Therefore, I want to...
0
1628
by: Chris F Clark | last post by:
In our C++ project we have some internal bug reporting macros that we use to get useful information when the program does something unexpected. Essentially at the point of the error, we invoke an internal interactive debugger that knows the classes within our system and allow us to walk around the objects that exist at the time of the...
8
5099
by: Ross A. Finlayson | last post by:
I'm trying to write some C code, but I want to use C++'s std::vector. Indeed, if the code is compiled as C++, I want the container to actually be std::vector, in this case of a collection of value types or std::vector<int>. So where I would use an int* and reallocate it from time to time in C, and randomly access it via , then I figure to...
0
1874
by: 42 | last post by:
I implemented a simple class inherited from Page to create a page template. It simply wraps some trivial html around the inherited page, and puts the inherited page into a form. The problem I have run into is that the emitted html at the end of the process is slightly different and doesn't work. Please don't be put off by all the source...
0
2020
by: ivan.leben | last post by:
I am writing this in a new thread to alert that I found a solution to the problem mentioned here: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/7970afaa089fd5b8 and to avoid this topic getting lost before people interested in the problem notice it. The important tricks to the solution are two: 1) make the custom classes...
2
1784
by: Monty | last post by:
Despite reading posts in Google, I don't understand XPATH. Can someone help me write an XPATH. From Google I think my problem is that the default namespace does not have a prefix. I can't change this as I have received this XML and I didn't create it. All I want to is retrieve the PROJECTNAME from the following XML. I am typing this XML and...
8
1864
by: obrianpatrick | last post by:
Hi, I am relatively new to object oriented programming and design. I am developing an application in VS 2005. I am having the following design problem: I have two interfaces X and Y. Y is derived from X as the following: __interface X {
6
1507
by: Christof Warlich | last post by:
Hi, can anyone tell how to convince the compiler to accept the third line in the example below? I need this parameter sequence because I want to define a default argument for T , e.g.: template<X<T*x, typename T = intstruct Y2{}; template<typename Tstruct X {}; template<typename T, X<T*xstruct Y1{};
0
7703
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7930
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7681
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7983
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6290
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5514
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5228
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
1
2118
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
950
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

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.