constructor that depends whether the object being constructed is const or not

H

Hicham Mouline

Hi,
is there a way to have 1 ctor called when I construct object of type O like
const O o(data); // o will not change after
and another ctor when I construct a non-const instance, for e.g.
O o;
or
O o(data);
and
o.add(more data);


i would then use different containers to store the data


regards,
 
J

JC2

Hi,
is there a way to have 1 ctor called when I construct object of type O like
const O o(data);  // o will not change after

No there is not.

and another ctor when I construct a non-const instance, for e.g.
O o;
or
O o(data);
and
o.add(more data);

The only way I can think of is to use something else to construct it,
e.g.:

class O {
public:
static O * newInstance () { return new O(false); }
static const O * newConstInstance () { return new O(true); }
private:
O (bool isconst) { ... }
};

i would then use different containers to store the data

The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.

-J
 
H

Hicham Mouline

Hi,
is there a way to have 1 ctor called when I construct object of type O
like
const O o(data); // o will not change after

No there is not.

and another ctor when I construct a non-const instance, for e.g.
O o;
or
O o(data);
and
o.add(more data);

The only way I can think of is to use something else to construct it,
e.g.:

class O {
public:
static O * newInstance () { return new O(false); }
static const O * newConstInstance () { return new O(true); }
private:
O (bool isconst) { ... }
};

i would then use different containers to store the data

The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.

-J
----------------------------------------------------------------------------------------------------------------------
I have a list of data points (x,y)

if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no dynamic
allocation whatsoever.


otherwise
Curve curve(begin iterator, end iterator )
I may then use vector<> for e.g., which is extensible but involves dynamic
allocation
 
K

Kai-Uwe Bux

Hicham said:
No there is not.



The only way I can think of is to use something else to construct it,
e.g.:

class O {
public:
static O * newInstance () { return new O(false); }
static const O * newConstInstance () { return new O(true); }
private:
O (bool isconst) { ... }
};



The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.

-J
----------------------------------------------------------------------------------------------------------------------
I have a list of data points (x,y)

if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no
dynamic allocation whatsoever.

Hm, the length of the sequence, i.e., distance( begin_iter, end_iter ) is
also known at compile time? If not, there will be dynamic allocation or you
arbitrarily limit the size of the list to some large number (in which case
most often you will actually waste memory).

Moreover, even if the size distance( begin_iter, end_iter ) is know at each
location it may differ from one location to another. In this case, you ave
the problem that the types array<T,n> are different if the n-values differ.
To encapsulate this polymorphism inside, the Curve type has to resort to
some trickery that most like will involve dynamic allocation.
otherwise
Curve curve(begin iterator, end iterator )
I may then use vector<> for e.g., which is extensible but involves dynamic
allocation

Have you measured the costs of dynamic allocation? After all, if the curve
is const, you have only one allocation upon construction and one
deallocation upon destruction, but no reallocations during the lifetime of
the curve.


Best

Kai-Uwe Bux
 
R

red floyd

The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.
I have a list of data points (x,y)

if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no dynamic
allocation whatsoever.

otherwise
Curve  curve(begin iterator, end iterator )
I may then use vector<> for e.g., which is extensible but involves dynamic
allocation

As Kai-Uwe mentioned, unless the size is known at compile time, you'd
have to dynamically allocate anyways.

You should probably just use vector, regardless. pseudo-code follows:

if (should be const)
const vector<Curve> const_vect(begin_iter, end_iter);
else
vector<Curve> vect(begin_iter, end_iter);
 
J

JC2

JC2 said:
[snip]
The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.
[snip]
if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no dynamic
allocation whatsoever.

otherwise
Curve  curve(begin iterator, end iterator )
I may then use vector<> for e.g., which is extensible but involves dynamic
allocation


First of all, this sounds like some premature optimization that will
likely not get you the performance benefits you are seeking. Does your
current implementation not meet your performance requirements? Are you
having performance issues that you need to solve? Is this really the
bottleneck? What you are attempting to do does not seem like a good
idea, it sounds like you may be headed down the wrong path.

Like Kai-Uwe Bux explained, if the size is known then there is only
one dynamic allocation on creation.


Also, I'm still not quite clear on what you are saying. Do you mean
that you would store Curve and const Curve in different containers,
e.g. vector<Curve> and array<const Curve,n>? Or do you mean that
within Curve, the storage you use to hold the data points is
different, e.g.:

class Curve {
...
vector<Point> points; // for non-const
array<Point,MAXSIZE> points; // for const
...
};


In both cases it's still a premature optimization with very little
effect. I'm assuming the latter case.

Basically you have two distinctly different types of Curves. If you
still insist on doing something (which IMHO is a bad idea), you could:

* Define a base Curve class, and derive ConstCurve and NonConstCurve
from it, with optimizations for the ConstCurve.
* Define a ConstCurve and NonConstCurve with the same interface and
use template tricks and specializations all around to optimize certain
operations for the ConstCurve case.
* Use Curve for the non-const case and simply use DataPoint[] arrays
for the const case, and overload time-critical functions with
optimized versions that accept DataPoint[] instead of Curve.


J
 
J

JC2

JC2 said:
[snip]
The real question is: What problem are you trying to solve? There is
likely a better way. This is a strange and unusual thing to want to
do.
[snip]
if I do
const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no dynamic
allocation whatsoever.
otherwise
Curve  curve(begin iterator, end iterator )
I may then use vector<> for e.g., which is extensible but involves dynamic
allocation

First of all, this sounds like some premature optimization that will
likely not get you the performance benefits you are seeking. Does your
current implementation not meet your performance requirements? Are you
having performance issues that you need to solve? Is this really the
bottleneck? What you are attempting to do does not seem like a good
idea, it sounds like you may be headed down the wrong path.

Like Kai-Uwe Bux explained, if the size is known then there is only
one dynamic allocation on creation.

Also, I'm still not quite clear on what you are saying. Do you mean
that you would store Curve and const Curve in different containers,
e.g. vector<Curve> and array<const Curve,n>? Or do you mean that
within Curve, the storage you use to hold the data points is
different, e.g.:

class Curve {
  ...
  vector<Point> points; // for non-const
  array<Point,MAXSIZE> points; // for const
  ...

};

In both cases it's still a premature optimization with very little
effect. I'm assuming the latter case.

Basically you have two distinctly different types of Curves. If you
still insist on doing something (which IMHO is a bad idea), you could:

  * Define a base Curve class, and derive ConstCurve and NonConstCurve
from it, with optimizations for the ConstCurve.
  * Define a ConstCurve and NonConstCurve with the same interface and
use template tricks and specializations all around to optimize certain
operations for the ConstCurve case.
  * Use Curve for the non-const case and simply use DataPoint[] arrays
for the const case, and overload time-critical functions with
optimized versions that accept DataPoint[] instead of Curve.


I hit send a bit too soon. I should point out that if you do any of
the above, it boils down to something like the difference between
accessing values in a double[] array and a vector<double> (the
"dynamic" allocation of the vector only occurring once at
initialization, as opposed to sticking the double[] on the stack). You
should ask yourself if this difference is really a bottleneck (or if
it even is affecting performance at all). There are likely better ways
to optimize (e.g. perhaps you are doing huge multiplies of data points
or something, maybe consider optimizing with SSE or something instead,
after determining where your bottlenecks are).

J
 
H

Hicham Mouline

class Curve {
...
vector<Point> points; // for non-const
array<Point,MAXSIZE> points; // for const
...

};

In both cases it's still a premature optimization with very little
effect. I'm assuming the latter case.

Basically you have two distinctly different types of Curves. If you
still insist on doing something (which IMHO is a bad idea), you could:

* Define a base Curve class, and derive ConstCurve and NonConstCurve
from it, with optimizations for the ConstCurve.
* Define a ConstCurve and NonConstCurve with the same interface and
use template tricks and specializations all around to optimize certain
operations for the ConstCurve case.
* Use Curve for the non-const case and simply use DataPoint[] arrays
for the const case, and overload time-critical functions with
optimized versions that accept DataPoint[] instead of Curve.


I hit send a bit too soon. I should point out that if you do any of
the above, it boils down to something like the difference between
accessing values in a double[] array and a vector<double> (the
"dynamic" allocation of the vector only occurring once at
initialization, as opposed to sticking the double[] on the stack). You
should ask yourself if this difference is really a bottleneck (or if
it even is affecting performance at all). There are likely better ways
to optimize (e.g. perhaps you are doing huge multiplies of data points
or something, maybe consider optimizing with SSE or something instead,
after determining where your bottlenecks are).

J
----------------------------------------------------------------------------------
We may have bursts of 1000 curve objects / second... we have profiled other
parts of the code
and we have seen large improvements of on stack vs dynamic allocations.
which yields me to believe there would be an advantage of implementing both
cases.

Our typical size of the curve is 10 data points, therefore
For the const curve case, boost::array< pair<>, 16 > seems to be the
appropriate container.
However we still want to handle the case of having more than 16 points , and
forward to the non const implementation.
For the non-const curve, vector< pair<> > is chosen. These probably reach in
the 100 entries. (i'm wondering what
to do here for the capacity of the vector)

Our basic pair is pair<int, double> or pair<double, double>

What we do with a curve is essentially construct it or without initial
points, const or non const, sometimes add more points later,
and finally extract the ordinate for an abscissa with the help of an
interpolator (template argument of the get member function)

Ideally, i'd like to offer 1 interface for all cases...

rds,
 
H

Hicham Mouline

Hendrik Schober said:
Hicham said:
[...]
I have a list of data points (x,y)

if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with a
maximum compile-time known size
and where no data is added after construction, this would involve no
dynamic allocation whatsoever.

But the iterators provide no known size at compile-time.
Am I missing something or are you missing something?

(If you need different behavior, why not provide your
class with a storage policy? Of course, then you might
have to implement the algorithms as templates.)

Schobi

the iterators are known at runtime
const Curve curve // this would be on stack if runtime size is <
compiletime max size of array
// the remainer would then be allocated on the
heap

"storage policy" : use boost::array or native arrays vs std::vector for
e.g.
I'll need to implement both.

thanks
 
K

Kai-Uwe Bux

Hicham Mouline wrote:

[snip]
We may have bursts of 1000 curve objects / second... we have profiled
other parts of the code
and we have seen large improvements of on stack vs dynamic allocations.
which yields me to believe there would be an advantage of implementing
both cases.

Our typical size of the curve is 10 data points, therefore
For the const curve case, boost::array< pair<>, 16 > seems to be the
appropriate container.
However we still want to handle the case of having more than 16 points ,
and forward to the non const implementation. [snip]
Ideally, i'd like to offer 1 interface for all cases...

I am not sure whether this applies to your problem, but it appears that you
are looking for some sort of optimization that applies to curves with
through a small number of points. That sounds similar to "small string
optimization", which was/is used in some implementations of std::string to
make it faster for short strings. I am not aware, however, of any
techniques that would distinguish const vs non-const strings for this
matter. In any case, maybe, you can use similar techniques to build the
Curve class.


Best

Kai-Uwe Bux
 
H

Hicham Mouline

Hendrik Schober said:
Hicham said:
Hendrik Schober said:
Hicham Mouline wrote:
[...]
I have a list of data points (x,y)

if I do

const Curve curve( begin iterator, end iterator );
I would then like to use for storage a container like boost::array with
a maximum compile-time known size
and where no data is added after construction, this would involve no
dynamic allocation whatsoever.
But the iterators provide no known size at compile-time.
Am I missing something or are you missing something?

(If you need different behavior, why not provide your
class with a storage policy? Of course, then you might
have to implement the algorithms as templates.)

[...]
Schobi

the iterators are known at runtime

What do you mean by saying this? Show some code.
If you want to use 'boost::array', you need an actual
compile-time constant to instantiate it. I can't see how
you are going to get this from iterators.
const Curve curve // this would be on stack if runtime size is <
compiletime max size of array
// the remainer would then be allocated on
the heap

"storage policy" : use boost::array or native arrays vs std::vector
for e.g.
I'll need to implement both.

I think you are a bit confused as to the means of "known
at compile-time". -- Or I'm confused as to what you are
saying what you want to do.
Anyway, to me it seems you should look into Kai-Uwe's
suggestion: small string optimization. That sounds pretty
much like what you are looking for -- although this does
not heed constness.

Schobi

I am sorry i am not being clear.
The idea is this:

I have a curve of points (x,y). The types of x and y would be template
arguments, but that's an irrelevant information.

There are curves which we would construct that are const, constructed once
and for all, and no points are ever added or changed.
const Curve<> curve1( begin xiterator, end xiterator, begin yiterator );
Most of these may have a size of 10 points or so.... I figured because of
this, a array<..., 10> would do for most cases.
end-begin is known only at runtime, but it is know that it's <= 10,
when it's >10, we could then put the remainder in a std::vector<>
knowing that this is a rare case, and so any cost of processing to select
between the underlying array<> or vector<> would be offset
by its rarity. This assumption will be proved by a profiler obviously.

There are also non-const curves. But these most often will have a more
variable number of points, and higher than 10, and so
we may want to use only the std::vector<>.
As there is not really a simple way to distinguish between const and
non-const ctors, except the workarounds from before,
I'd say I'd stick to implementation number 1 for both cases.
 
H

Hicham Mouline

Hendrik Schober said:
Hicham said:
[...]
The idea is this:

I have a curve of points (x,y). The types of x and y would be template
arguments, but that's an irrelevant information.

There are curves which we would construct that are const, constructed
once and for all, and no points are ever added or changed.
const Curve<> curve1( begin xiterator, end xiterator, begin yiterator );

This doesn't compile. I don't know what 'begin xiterator'
means, nor any of the other. How do you suppose I can tell
you if this compiles and why?
From the little I know I presume there's no way to get a
compile-time constant size from the iterators. But that's
what you need for instantiating 'boost::array'.

Schobi

I'm sorry i was just writing pseudo-code

I take a maxsize for boost::array
if the runtime size happens to be bigger than maxsize
i then have to deal with it.
 
H

Hicham Mouline

Hendrik Schober said:
Hicham said:
[...]
I take a maxsize for boost::array
if the runtime size happens to be bigger than maxsize
i then have to deal with it.

But then the discriminating factor isn't whether the object
is const or not, but whether the data fits into the fixed-
size array. After all, if it does fit, why not put non-const
curves' data into the (faster) array, too?
This smells a lot like the small-string optimization to me.
Have you looked into that one?

Schobi

I thought constness might simplify the implementation
in that we know adding points would not be possible,
but that doesn't really help. you are right.

I will look into small-string optimization.

thanks very much,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top