template codegeneration issues

  • Thread starter Thread starter Serge Skorokhodov (216716244)
  • Start date Start date
S

Serge Skorokhodov (216716244)

Hi,

I just seeking advice.

Some background information first because I've run into issues
that seems pretty obscure to me:( Quick search through KB yields
next to nothing. Simplified samples work OK as well, the problems
appear in rather bulky code:(

I'm trying to implement some signal processing algorithm using
templates with integral template arguments (sampling rate, window
and delay sizes etc.) in VC 7.1. The template classes contain
static and non-static const members that depend on template
arguments. Some of these classes are used as template arguments
in higher level classes.

The problems:

1. The values of non-static const members is changed in run-time.
It can be easily observed in the debbuger and it looks like
certain member variables and const members are placed at the same
memory locations. A simplified illustration may be like this:

template < int sr >
myContainedClass
{
public:
myContainedClass() { /* some code */ }
void reset_internals() { /* some code */ }

private
static const int buf_sz = int(sr*80.0/1000.0 + 0.5);
int buffer[buf_sz];
};

template < class contained_class_t, int sr >
class myClass
{
public:
myClass() : contained_class(sr), some_const(0.5)
{
// some_const == 0.5 here
contained_class.reset_internals();
// some_const == some other value here
}
private:
contained_class_t contained_class;
const double some_const;
};

2. The members of different variables of the abovementioned
template classes seem to similarly "overlap" in memory:(

SomeClass var1( /*some initialization args*/);
myClass<500> var2;
// here some var1 data is corrupted by the code of var2 ctor:(

Adding additional "dummy" data members may eliminate the errors.

Is it a known problem? Can somebody make a suggestion how to
avoid it? Maybe a workaround? I understand that using other
(simpler:) coding style will help. But I really enjoy both
flexibility and performance that C++ templates promise;)

Sorry for not messy posting but I really failed to demonstrate a
problem in a simple and short code snippet:(

TIA
 
Serge said:
Hi,

I just seeking advice.

Some background information first because I've run into issues
that seems pretty obscure to me:( Quick search through KB yields
next to nothing. Simplified samples work OK as well, the problems
appear in rather bulky code:(

I'm trying to implement some signal processing algorithm using
templates with integral template arguments (sampling rate, window
and delay sizes etc.) in VC 7.1. The template classes contain
static and non-static const members that depend on template
arguments. Some of these classes are used as template arguments
in higher level classes.

The problems:

1. The values of non-static const members is changed in run-time.
It can be easily observed in the debbuger and it looks like
certain member variables and const members are placed at the same
memory locations. A simplified illustration may be like this:

template < int sr >
myContainedClass
{
public:
myContainedClass() { /* some code */ }
void reset_internals() { /* some code */ }

private
static const int buf_sz = int(sr*80.0/1000.0 + 0.5);
int buffer[buf_sz];
};

You should probably define buf_sz:

template <int sr>
const int myContainedClass::buf_sz;

It is undefined behaviour (or is it ill-formed?) to use buf_sz as
anything but a integral constant expression if you don't have the
definition. For example, you can't pass it to a function, or assign it
to any variable.
template < class contained_class_t, int sr >
class myClass
{
public:
myClass() : contained_class(sr), some_const(0.5)
{
// some_const == 0.5 here
contained_class.reset_internals();
// some_const == some other value here
}
private:
contained_class_t contained_class;
const double some_const;
};

2. The members of different variables of the abovementioned
template classes seem to similarly "overlap" in memory:(

SomeClass var1( /*some initialization args*/);
myClass<500> var2;
// here some var1 data is corrupted by the code of var2 ctor:(

Adding additional "dummy" data members may eliminate the errors.

Is it a known problem? Can somebody make a suggestion how to
avoid it? Maybe a workaround? I understand that using other
(simpler:) coding style will help. But I really enjoy both
flexibility and performance that C++ templates promise;)

I've not come across this, no. Without seeing a full(er) example, it's
hard to say whether it is a compiler bug or your code at fault.

Tom
 
Tom Widmer [VC++ MVP] wrote:

Thanks for prompt responce.

You should probably define buf_sz:

template <int sr> const int myContainedClass::buf_sz;

It is undefined behaviour (or is it ill-formed?) to use buf_sz
as anything but a integral constant expression if you don't
have the definition. For example, you can't pass it to a
function, or assign it to any variable.

I thought about defining constands outside the class but
I haven't think it's UB to define them inside class definition
the way I do:(

It isn't undefined behaviour to use such an outside defined
constant as member array size?

I've not come across this, no. Without seeing a full(er)
example, it's hard to say whether it is a compiler bug or your
code at fault.

Unfortunalely fuller example is rather bulky and has plenty
dependences, as usual:(
And I don't have time to construct "mid-sized" examples either:(

Thanks anyway. You suggestions will certainly help.

Another question. I use template arguments and static member
consts for (maybe imaginary;) performance advantages. If member
constants are to be defined outside the class definition, it
doesn't make much sence to calculate them at compile time using
template arguments etc.? Passing arguments to class constructor
and initializing member constants in initialization list should
result in the same performance without using templates? What
would you suggest?

TIA
 
Serge said:
Tom Widmer [VC++ MVP] wrote:

Thanks for prompt responce.

You should probably define buf_sz:

template <int sr> const int myContainedClass::buf_sz;

It is undefined behaviour (or is it ill-formed?) to use buf_sz
as anything but a integral constant expression if you don't
have the definition. For example, you can't pass it to a
function, or assign it to any variable.


I thought about defining constands outside the class but
I haven't think it's UB to define them inside class definition
the way I do:(

It isn't undefined behaviour to use such an outside defined
constant as member array size?

Static integral const variables in classes can still be defined, but you
have to leave off the initializer in the definition. I literally meant
to add the code I wrote directly below the existing class. e.g.

template <class T>
struct Foo
{
static int const Bar = 10; //value defined here
}

template <class T>
int const Foo said:
Unfortunalely fuller example is rather bulky and has plenty
dependences, as usual:(
And I don't have time to construct "mid-sized" examples either:(

Thanks anyway. You suggestions will certainly help.

Another question. I use template arguments and static member
consts for (maybe imaginary;) performance advantages. If member
constants are to be defined outside the class definition, it
doesn't make much sence to calculate them at compile time using
template arguments etc.? Passing arguments to class constructor
and initializing member constants in initialization list should
result in the same performance without using templates? What
would you suggest?

This point is moot given the above. Define the value in the class
definition and the compiler will use it directly where possible. The
point is that the compiler may also require the variable to have storage
defined (obvious cases include taking the variable's address and binding
it to a reference, but the standard requires it for almost any use
except using it as an array bound or as the argument to another non-type
template parameter). To clarify:

struct Foo
{
static int const Bar = 10;
int array[Bar];
};

Perfectly legal so far. But:

int main()
{
int i = Foo::Bar; //illegal
&Foo::Bar; //illegal
int const& ref = Foo::Bar; //illegal
}
//But add this to make the above all legal.
int const Foo::Bar;

Tom
 
Back
Top