473,385 Members | 2,274 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,385 software developers and data experts.

Optional template constructor parameters?

Dear List,

I have a class that may or may not have several features. For example,
there might be "partition" to d_data of obj. The code is like (please
ignore grammar mistakes):

template<typename T>
struct obj
{
vector<T> d_data;
obj(T init_value);
};

template<typename T>
struct Partition
{
vector<int> d_index;
Partition(vector<int> ind);
};

I do not want to create templates for each combination of features so I
would like to use something like a policy-based design:

template<typename T,
template <class s> class feature1,
template <class s> class feature2>
struct obj: public feature1<T>, feature2<T>
{
vector<T> d_data;
obj(T init_value);
};

typedef template<int, Partition> intDataWithPartition;

In this way, I can get data member d_index (and methods to operate on
it) from Parition class. However, this will not work since I can not
provide constructor to Partition<T> from obj::obj(). Is there any
workaround? Am I going a totally wrong way?

Many thanks in advance.
Bo
Jul 22 '05 #1
7 3604
On Mon, 05 Jul 2004 15:50:40 -0500, Bo Peng <bp***@rice.edu> wrote:
Dear List,

I have a class that may or may not have several features. For example,
there might be "partition" to d_data of obj. The code is like (please
ignore grammar mistakes):

template<typename T>
struct obj
{
vector<T> d_data;
obj(T init_value);
};

template<typename T>
struct Partition
{
vector<int> d_index;
Partition(vector<int> ind);
};

I do not want to create templates for each combination of features so I
would like to use something like a policy-based design:

template<typename T,
template <class s> class feature1,
template <class s> class feature2>
struct obj: public feature1<T>, feature2<T>
{
vector<T> d_data;
obj(T init_value);
};

typedef template<int, Partition> intDataWithPartition;

In this way, I can get data member d_index (and methods to operate on
it) from Parition class. However, this will not work since I can not
provide constructor to Partition<T> from obj::obj(). Is there any
workaround? Am I going a totally wrong way?


You need to decide on the interface to the policies. In this case, it
looks like they need at least the d_data vector passed to their
constructors. e.g.

obj(T init_value)
:feature1<T>(d_data), feature2<T>(d_data)
{
}

Note that a) you can only pass a reference to members of obj to a base
class, and b) you mustn't do anything with that reference until the
obj constructor body is reached (since it is only by then that the
d_data member has been constructed).

Alternatively, you could add an init member to each policy (which
takes a templated obj& parameter probably), and call that in the obj
constructor, passing whatever is necessary.

The main thing is to pin down a required interface or interfaces that
the feature1 and feature2 policies must implement.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #2
tom_usenet wrote:
You need to decide on the interface to the policies. In this case, it
looks like they need at least the d_data vector passed to their
constructors. e.g.

obj(T init_value)
:feature1<T>(d_data), feature2<T>(d_data)
{
}
Note that a) you can only pass a reference to members of obj to a base
class, and b) you mustn't do anything with that reference until the
obj constructor body is reached (since it is only by then that the
d_data member has been constructed).
This is a strange way of doing things since feature1<T>() will be
created before obj. Data passed to feature1<T> should be considered
junk, right?
Alternatively, you could add an init member to each policy (which
takes a templated obj& parameter probably), and call that in the obj
constructor, passing whatever is necessary.


The init member functions can only do default construction, but I need
to construct Partition with parameters which, from what I understand,
can only be passed from the parameters of obj::obj(). For example:

obj::obj(T init_value, optional vector<int> d_index if Parition is
featured):feature1<T>(d_index), ....
{

}

Since the numbers of parameters of obj::obj() will change, even partial
instantiation will not work. There are something called boost::enable_if
but I am not sure if it can do the magic.

Bo
Jul 22 '05 #3
Bo Peng wrote:
tom_usenet wrote:
You need to decide on the interface to the policies. In this case, it
looks like they need at least the d_data vector passed to their
constructors. e.g.

obj(T init_value)
:feature1<T>(d_data), feature2<T>(d_data)
{
}
Note that a) you can only pass a reference to members of obj to a base
class, and b) you mustn't do anything with that reference until the
obj constructor body is reached (since it is only by then that the
d_data member has been constructed).

This is a strange way of doing things since feature1<T>() will be
created before obj. Data passed to feature1<T> should be considered
junk, right?


The value of d_data is junk (uninitialised), but if your 'feature1'
expects a reference, then d_data is OK because the storage has already
been created and the reference to it would be a valid one. You cannot
use it in the 'feature1' constructor, except to store it or to take
its address.
[...]


From what I saw, you didn't provide enough information to give any
particular solution. How does 'feature1' ('Partition' in your case)
initialise itself? Does it have to have the vector (already filled in),
or would the size of that data vector be enough? Would it try to alter
any other member data in 'obj'?

V
Jul 22 '05 #4
Victor Bazarov wrote:
From what I saw, you didn't provide enough information to give any
particular solution. How does 'feature1' ('Partition' in your case)
initialise itself? Does it have to have the vector (already filled in),
or would the size of that data vector be enough? Would it try to alter
any other member data in 'obj'?


These are undecided details of features. Of course features can be
initialized and given meaningful values later. For example

template<typename T>
struct Partition
{
vector<int> d_index;
Partition():d_index(0){}; // default constructor
setPartition(vector<int> i){ d_index = i; );
};

template<typename T,
template <class s> class feature1,
template <class s> class feature2>
struct obj: public feature1<T>, feature2<T>
{
vector<T> d_data;
obj(int length, T init_value):d_data(length),
feature1<T>(), feature2<T>()
{
fill(d_data.begin(), d_data.end(), init_value);
};
};

typedef template<int, Partition> intDataWithPartition;

intDataWithPartition data(100, 1) // initialize d_data
vector<int> par(2);
par[0]=10, par[1]=90;
data.setPartition(par);

What I wanted was a customized constructor that can accept different
parameters when using differnt policies, something like

vector<int> par(2);
par[1]=10, par[2]=90;
intDataWithParition data(100, 1, par)

Bo

Jul 22 '05 #5
On Wed, 07 Jul 2004 01:09:32 -0500, Bo Peng <bp***@rice.edu> wrote:
typedef template<int, Partition> intDataWithPartition;

intDataWithPartition data(100, 1) // initialize d_data
vector<int> par(2);
par[0]=10, par[1]=90;
data.setPartition(par);
From your example it is unclear why Partition is a base class of obj -
it appears to have nothing to do with it. Can't it just be a separate
object? Inheritence is very tight coupling.

You appear to be using policies is a rather strange way. Policies are
there to change the behaviour of a class, not to extend its
functionality, and to change the behaviour of the class, the class
must call back into them. For this to happen, they must implement a
fixed interface. See "Modern C++ Design" for details.
What I wanted was a customized constructor that can accept different
parameters when using differnt policies, something like

vector<int> par(2);
par[1]=10, par[2]=90;
intDataWithParition data(100, 1, par)


Hmm, this is probably more work than it's worth. One approach would be
to provide lots of overloads of the constructor, and use
metaprogramming to work out how to forward the arguments to the policy
constructors. But why not just call setPartition, or define some
common requirements for the policies so that you don't need custom
code to handle each policy.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #6
tom_usenet wrote:
From your example it is unclear why Partition is a base class of obj -
it appears to have nothing to do with it. Can't it just be a separate
object? Inheritence is very tight coupling.
Partition is a partition to d_data in class obj, I have to use one of
the following ways to put them together:

class obj: class Partition // Partition provide d_index
class PartitionedObj : class obj // sounds more natural
class obj{ // a bit more difficult to use
class Partition par;
...
}

To use a policy-based approach, because there will be other features,
only the first form makes sense.
You appear to be using policies is a rather strange way. Policies are
there to change the behaviour of a class, not to extend its
functionality, and to change the behaviour of the class, the class
must call back into them. For this to happen, they must implement a
fixed interface. See "Modern C++ Design" for details.
I agree with this. Policy based design might not work for me here.
Please allow me to re-phrase my problem:

1. I have a base class obj
2. There might be several optional extensions to obj
3. users might want one or more extensions.

Currently, I am using a big obj with all the extensions. Most of them
are latent in the sense that they are in class obj but unused.

class obj{
feature1 f1;
feature2 f2;
...
obj(parameter_for_f1 = NULL, parameter_for_f2 = empty_vector
):f1(parameter_for_f1), f2(parameter_for_f2){ }
}

I am not satisfied with this big class (maybe this is the best solution)
but the following is too tedious when the combination of features get big:

class objFeature1:public baseobj{
feature1 f1;
objFeature1( parameter_for_f1)
:f1(parameter_for_f1){}
}
class objFeature2:public baseobj{
feature1 f2;
objFeature2( parameter_for_f2)
:f2(parameter_for_f2){}
}
class objFeature1And2:public baseobj{
feature1 f1;
feature2 f2;
objFeature1( parameter_for_f1, parameter_for_f2)
:f1(parameter_for_f1), f2(parameter_for_f2){}
}
....

Policy-based design is my attempt to treat these classes in a uniform way.

Hmm, this is probably more work than it's worth. One approach would be
to provide lots of overloads of the constructor, and use
metaprogramming to work out how to forward the arguments to the policy
constructors. But why not just call setPartition, or define some
common requirements for the policies so that you don't need custom
code to handle each policy.


I guess this is the way to go, but it is hard to find common interface
to these policies.

Thanks.
Bo
Jul 22 '05 #7
On Wed, 07 Jul 2004 11:32:02 -0500, Bo Peng <bp***@rice.edu> wrote:
I agree with this. Policy based design might not work for me here.
Please allow me to re-phrase my problem:

1. I have a base class obj
2. There might be several optional extensions to obj
3. users might want one or more extensions.

Currently, I am using a big obj with all the extensions. Most of them
are latent in the sense that they are in class obj but unused.

class obj{
feature1 f1;
feature2 f2;
...
obj(parameter_for_f1 = NULL, parameter_for_f2 = empty_vector
):f1(parameter_for_f1), f2(parameter_for_f2){ }
}

I am not satisfied with this big class (maybe this is the best solution)
but the following is too tedious when the combination of features get big:

class objFeature1:public baseobj{
feature1 f1;
objFeature1( parameter_for_f1)
:f1(parameter_for_f1){}
}
class objFeature2:public baseobj{
feature1 f2;
objFeature2( parameter_for_f2)
:f2(parameter_for_f2){}
}
class objFeature1And2:public baseobj{
feature1 f1;
feature2 f2;
objFeature1( parameter_for_f1, parameter_for_f2)
:f1(parameter_for_f1), f2(parameter_for_f2){}
}
...

Policy-based design is my attempt to treat these classes in a uniform way.


Ok, how about making each feature offer the typedef
"constructor_parameter_type" and the static method
"get_default_constructor_parameter" (feel free to shorten the names).
e.g.

class feature1
{
protected:
typedef std::vector<int> const& constructor_parameter_type;
static std::vector<int> get_default_constructor_parameter()
{
return std::vector<int>();
}

feature1(std::vector<int> const& param);
};
class NullFeature
{
protected:
typedef int constructor_parameter_type;
static int get_default_constructor_parameter()
{
return 0;
}
NullFeature(int){}
};

(with as many features are required:)
template <class Feature1 = NullFeature, class Feature2 = NullFeature>
class obj: public Feature1, public Feature2
{
public:
obj(typename Feature1::constructor_parameter_type p1 =
Feature1::get_default_constructor_parameter(),
typename Feature2::constructor_parameter_type p2 =
Feature2::get_default_constructor_parameter())
:Feature1(p1), Feature2(p2)
{
}
};

Hopefully the empty base optimization will keep sizeof(obj<>) to a
minimum.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #8

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

Similar topics

4
by: Sebastian Faust | last post by:
Hi, I have 4 questions related to templates. I wanna do something like the following: template<typename T> class Template { public: Template_Test<T>()
3
by: Gandu | last post by:
Could some C++ guru please help me. I have a template based general linked list class that I want to inherit publicly to create a queue class. In the case of non-template inheritance, I can use:...
2
by: max_sang | last post by:
Hello I have a nasty problem... take a look at this code: struct Parser { Parser(const string& s) { ... tokenizes s into pieces... } template <class T> to(size_t idx); private: vector<string>...
14
by: Bart Samwel | last post by:
Hi everybody, I would really like some help explaining this apparent discrepancy, because I really don't get it. Here is the snippet: void foo(int&); void foo(int const&); ...
10
by: ma740988 | last post by:
Part of my confusion here is certainly my ignorance of templates and std::auto_ptr. Two topics, I've perused but need to really _delve_ into. In any event, consider the 'test' source. #...
12
by: Nick Hounsome | last post by:
Can anyone tell me what the rational is for not supporting optional arguments. It is obviously a trivial thing to implement and, since C++ has them, I would not expect them to be omitted without...
12
by: pamelafluente | last post by:
Hi guys, In the past I have used several time optional parameters in my function. But Now I am more inclined to think that they are more dangerous than useful, and probably better to be...
12
by: aaragon | last post by:
Hello all. I have a simple question that seems trivial but I can't make it to work. I have a class that takes as a template argument, another class. The idea is as follows: #include...
3
by: Fred Kleinschmidt | last post by:
I have a template:: template <class Vclass Vct { public: Vct(V); }; template <class V> Vct<V>::Vct( V vin ) { /*...*/
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: 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
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
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,...

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.