473,883 Members | 1,599 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Why avoid constant template parameter

Hello Experts!

What does this mean actually.

If you have a template with a type and non-type template argument, say, like
this
template<typena me T, int a>
class Array {. . .};

then A<int, 1> and A<int, 2> are different types. Now, if the A template
had some code (implementation ), then if it's used, it would be
_instantiated_ for
every template instantiation, which may lead to code "bloat".

I mean that in main below I instansiate 10 objects using constant parameter
to the
class template which is not good.
So this will mean that I will create 10 different types because I create 10
objects.
We can also assume that the implamentation code is quite large in class
template Array.

At what situations will the object file be great on account of using
constant template parameter.
Give me some good example on this.
It's only the instansiated objects that really allocate memory.
Will it be big in this example with 10 objects?
If I instead had instansiated 100 object of this class template array
would the object file be big then.

I can't see why the object code would expand just because we have constant
template parameter. It's only when you instansiate object by value you
allocate memory which will cause the object file to expand.

int main()
{
Array<int,1> a1;
Array<int,2> a2;
Array<int,3> a3;
Array<int,4> a4;
Array<int,5> a5;
Array<int,6> a6;
Array<int,7> a7;
Array<int,8> a8;
Array<int,9> a9;
Array<int,10> a10;

return 0;
}

Many thanks
Aug 20 '05 #1
8 3159
Tony Johansson wrote:
....
I can't see why the object code would expand just because we have constant
template parameter. It's only when you instansiate object by value you
allocate memory which will cause the object file to expand.

Consider this:
template<typena me T, int a>
class Array
{
Array()
{
... really big complicated, huge even, code ...
... and then some ...
}

};
Your code could instantiate the Array constructor 10 times. That might
be 10 times more code than if you did:
template<typena me T>
class Array
{
Array( int a )
{
... really big complicated, huge even, code ...
... and then some ...
}

};
However, if your code is small and inlineable, it would probably make
very little difference.

Aug 20 '05 #2

"Gianni Mariani" <gi*******@mari ani.ws> skrev i meddelandet
news:Mp******** ************@sp eakeasy.net...
Tony Johansson wrote:
...
I can't see why the object code would expand just because we have
constant
template parameter. It's only when you instansiate object by value you
allocate memory which will cause the object file to expand.

Consider this:
template<typena me T, int a>
class Array
{
Array()
{
... really big complicated, huge even, code ...
... and then some ...
}

};
Your code could instantiate the Array constructor 10 times. That might be
10 times more code than if you did:

template<typena me T>
class Array
{
Array( int a )
{
... really big complicated, huge even, code ...
... and then some ...
}

};

I can't understand why it should be any major difference
What is simalar between these two well both instansiate the same number of
objects
in this example 10. What is different between these two well in the one
example
we instansiate each object by passing an int to the constructor. In the
other example we instansiate
each object after the class template has been specilized to an int in this
case.

So what do you mean when you say this. I can't follow your minds here.
Your code could instantiate the Array constructor 10 times. That might
be 10 times more code than if you did:
template<typena me T>
class Array
{
Array( int a )
{
... really big complicated, huge even, code ...
... and then some ...
}

};

//Tony


In this example that you showed me
template<typena me T>
class Array
{
Array( int a )
{
... really big complicated, huge even, code ...
... and then some ...
}
};
Aug 20 '05 #3

"Tony Johansson" <jo************ *****@telia.com > wrote in message
news:Dr******** ***********@new sb.telia.net...
Hello Experts!

What does this mean actually.

If you have a template with a type and non-type template argument, say, like this
template<typena me T, int a>
class Array {. . .};

then A<int, 1> and A<int, 2> are different types. Now, if the A template
had some code (implementation ), then if it's used, it would be
_instantiated_ for
every template instantiation, which may lead to code "bloat".

I mean that in main below I instansiate 10 objects using constant parameter to the
class template which is not good.
So this will mean that I will create 10 different types because I create 10 objects.
We can also assume that the implamentation code is quite large in class
template Array.

At what situations will the object file be great on account of using
constant template parameter.
Give me some good example on this.
It's only the instansiated objects that really allocate memory.
Will it be big in this example with 10 objects?
If I instead had instansiated 100 object of this class template array
would the object file be big then.

I can't see why the object code would expand just because we have constant
template parameter. It's only when you instansiate object by value you
allocate memory which will cause the object file to expand.

int main()
{
Array<int,1> a1;
Array<int,2> a2;
Array<int,3> a3;
Array<int,4> a4;
Array<int,5> a5;
Array<int,6> a6;
Array<int,7> a7;
Array<int,8> a8;
Array<int,9> a9;
Array<int,10> a10;

return 0;
}

Many thanks


I think this question has a design consideration:

Pattern (a)
template<typena me T, int a>
class Array {. . .};

where the int a parameter might specify the size of the array of "T'".s

Pattern (b).
template<typena me T >
class Array {. . .};
( the size of Array is determined at runtime )

In pattern(a), we are "hardcoding " the size of the instance of Array at
compile time. In situation b), the
instance of Array can be dynamically sized, say, as a constructor parameter.

Now if you instantiate 10 classes A<char, 1>, A<char, 2), etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
In Pattern ( b), only one set of code will be generated for each distinct
type generated by
Array<>.

Pattern (a) might be desirable since this might be more efficient at
runtime,
you'll give up a bit of code bloat for super fast implementations of your
classes,
whereas b) might be acceptable if runtime efficiency is not the highest
priority, but we
would like to control the size of generated code.

I've developed code using the pattern (a) in a digital simulation system I
worked on.
This pattern was applied in a number of circumstances, but here's one as an
example: Logic "gates" have 1,2,3,4, etc inputs, we found that specializing
code
for 1,2,3,4, etc inputs using templates allowed us to develop very
efficient code to
evaluate logic functions over the general purpose code which looped over
each input
value & computed a result.

Of course, we accepted the necessary code bloat as a trade off for higher
runtime performance.
In conclusion, patterns (a) & (b) have their place in the C++ developers
toolbox,
just be aware of the benefits and consequences.

dave



Aug 21 '05 #4

"Dave Townsend" <da********@com cast.net> skrev i meddelandet
news:y7******** ************@co mcast.com...

"Tony Johansson" <jo************ *****@telia.com > wrote in message
news:Dr******** ***********@new sb.telia.net...
Hello Experts!

What does this mean actually.

If you have a template with a type and non-type template argument, say,

like
this
template<typena me T, int a>
class Array {. . .};

then A<int, 1> and A<int, 2> are different types. Now, if the A
template
had some code (implementation ), then if it's used, it would be
_instantiated_ for
every template instantiation, which may lead to code "bloat".

I mean that in main below I instansiate 10 objects using constant

parameter
to the
class template which is not good.
So this will mean that I will create 10 different types because I create

10
objects.
We can also assume that the implamentation code is quite large in class
template Array.

At what situations will the object file be great on account of using
constant template parameter.
Give me some good example on this.
It's only the instansiated objects that really allocate memory.
Will it be big in this example with 10 objects?
If I instead had instansiated 100 object of this class template array
would the object file be big then.

I can't see why the object code would expand just because we have
constant
template parameter. It's only when you instansiate object by value you
allocate memory which will cause the object file to expand.

int main()
{
Array<int,1> a1;
Array<int,2> a2;
Array<int,3> a3;
Array<int,4> a4;
Array<int,5> a5;
Array<int,6> a6;
Array<int,7> a7;
Array<int,8> a8;
Array<int,9> a9;
Array<int,10> a10;

return 0;
}

Many thanks


I think this question has a design consideration:

Pattern (a)
template<typena me T, int a>
class Array {. . .};

where the int a parameter might specify the size of the array of "T'".s

Pattern (b).
template<typena me T >
class Array {. . .};
( the size of Array is determined at runtime )

In pattern(a), we are "hardcoding " the size of the instance of Array at
compile time. In situation b), the
instance of Array can be dynamically sized, say, as a constructor
parameter.

Now if you instantiate 10 classes A<char, 1>, A<char, 2), etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
In Pattern ( b), only one set of code will be generated for each distinct
type generated by
Array<>.


Still I can't understand why the object code will be greater if you use
constant class template parameter.

In this example Now if you instantiate 10 classes A<char, 1>, A<char, 2),
etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
Do you here mean 10 objects each instanciated from its own class because we
will create 10 different but
slightly similar classes.

On the other hand in pattern(b) where you pass an int to a constructor just
for being able tell the size
for the array that exist in the concrete class I mean you do
Array a1(1), Array a2(2), Array a3(3), Arraya a4(4) until Array
a10(10) .
You will also here create 10 object just the same as you did for pattern(a).

Well I can't see any major difference.
In pattern(a) you create classes and then objects based on the created
class. For example the size for the array that exist within each generated
class is defined at compile time The constant class template parameter tell
the size for the array within the class template.

In pattern(b) you also create objects but from a concrete class. The array
that exist within this concrete class is passed at runtime. But you also
here create 10 different object each with a different size of
the array that exist within in the concrete will here.

As a summary in both cases for pattern(a) and pattern(b) you vill create 10
different objects with
the size of the array located in the class template and in the concrete
class specified in different ways.
In pattern(a) by using the constant class parameter and for pattern(b)
specified at run-time by passing a value to the constructor.

Pattern(a) will have 10 different objects called a1,a2,a3,a4,a5, a6,a7,a8,a9
and a10 the number tell the size of the array located in the class template.
The definition of the array located in the class template is
T array[size]; So Array <int,7> a7; will create an int array with the size
of 7.
Pattern(b) will have 10 different objects called a1, a2, a3, a4, a5, a6, a7,
a8,a9,a10 the size of the array will be passed in the constructor. So for
example Array a7(7); will crete an object called a7 with the size of the
local array defined in the concrete as int array[7];

//Tony
Aug 21 '05 #5
Le dimanche 21 août 2005 à 10:08:00, Tony Johansson a écrit dans
comp.lang.c++*:
I think this question has a design consideration:

Pattern (a)
template<typena me T, int a>
class Array {. . .};

where the int a parameter might specify the size of the array of "T'".s

Pattern (b).
template<typena me T >
class Array {. . .};
( the size of Array is determined at runtime )

In pattern(a), we are "hardcoding " the size of the instance of Array at
compile time. In situation b), the
instance of Array can be dynamically sized, say, as a constructor
parameter.

Now if you instantiate 10 classes A<char, 1>, A<char, 2), etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
In Pattern ( b), only one set of code will be generated for each distinct
type generated by
Array<>.
Still I can't understand why the object code will be greater if you use
constant class template parameter.

In this example Now if you instantiate 10 classes A<char, 1>, A<char, 2),
etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
Do you here mean 10 objects each instanciated from its own class because we
will create 10 different but
slightly similar classes.


Yes, there will be 10 slightly different constructors, 10 slightly
different destructors, and so on. The 10 calls in your main() function
call 10 different constructors.

Class1::Class1( ) { }
Class2::Class2( ) { }
Class3::Class3( ) { }
....

int main()
{
// calls Class1::Class1( );
// calls Class2::Class2( );
// calls Class3::Class3( );
....
}
On the other hand in pattern(b) where you pass an int to a constructor just
for being able tell the size
for the array that exist in the concrete class I mean you do
Array a1(1), Array a2(2), Array a3(3), Arraya a4(4) until Array
a10(10) .
You will also here create 10 object just the same as you did for pattern(a).


10 objects of the same class. There is only one constructor, one
destructor, and so on. The 10 calls in your main() function call the
same function.

Class::Class(in t n) { }

int main()
{
// calls Class::Class(1) ;
// calls Class::Class(2) ;
// calls Class::Class(3) ;
....
}

--
___________ 21/08/2005 10:41:07
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763
Aug 21 '05 #6
Tony Johansson wrote:

"Dave Townsend" <da********@com cast.net> skrev i meddelandet [snip]
Pattern (a)
template<typena me T, int a>
class Array {. . .};

where the int a parameter might specify the size of the array of "T'".s

Pattern (b).
template<typena me T >
class Array {. . .};
( the size of Array is determined at runtime )

In pattern(a), we are "hardcoding " the size of the instance of Array at
compile time. In situation b), the
instance of Array can be dynamically sized, say, as a constructor
parameter.

Now if you instantiate 10 classes A<char, 1>, A<char, 2), etc based upon
Pattern (a),
you will indeed generate 10 separate pieces of code, each similar but
slightly different.
In Pattern ( b), only one set of code will be generated for each
distinct type generated by
Array<>.


Still I can't understand why the object code will be greater if you use
constant class template parameter.

[snip]in both cases for pattern(a) and pattern(b) you vill create
10 different objects with
the size of the array located in the class template and in the concrete
class specified in different ways.
In pattern(a) by using the constant class parameter and for pattern(b)
specified at run-time by passing a value to the constructor.

Pattern(a) will have 10 different objects called
a1,a2,a3,a4,a5, a6,a7,a8,a9 and a10 the number tell the size of the array
located in the class template. The definition of the array located in the
class template is
T array[size]; So Array <int,7> a7; will create an int array with the
size of 7.
Pattern(b) will have 10 different objects called a1, a2, a3, a4, a5, a6,
a7, a8,a9,a10 the size of the array will be passed in the constructor. So
for example Array a7(7); will crete an object called a7 with the size of
the local array defined in the concrete as int array[7];

//Tony


You need to distinguish:

a) code size (generated by the compiler)
b) memory consumption at run time

Code Size depends on the number of different *types* (Classes) that you use
in your program. Since the instantiations of the Array<> template are
different classes the compiler will generate code for dealing with each of
them. That determines code size.

Memory consumption at run time depends on how many *objects* your program
creates during execution.

Thus, the fact that in both patterns the same number of objects are created
at run time is immaterial as far as code size is concerned.
Best

Kai-Uwe Bux

ps: If you want to torture your compiler and produce a really big object
file, compile the following into somefile.o and look at the file size. Do
not be surprised to find a really big object file: this snippet produces
about 10000 instantiations and dumps code for each of it into the object
file. Note that no objects are created at all.

// addition_table. cc

template < unsigned long A_MAX, unsigned long B_MAX >
struct arithmetic {

enum { sum = A_MAX + B_MAX };

static
unsigned long inc ( unsigned long a ) {
// return B_MAX + a
if ( a == A_MAX ) {
return( arithmetic< A_MAX, B_MAX >::sum );
}
return( arithmetic< A_MAX-1, B_MAX >::inc( a ) );
}

static
unsigned long add ( unsigned long a, unsigned long b ) {
if ( a == A_MAX ) {
return( arithmetic< B_MAX, A_MAX >::inc( b ) );
}
return( arithmetic< A_MAX-1, B_MAX >::add( a, b ) );
}

};

template < unsigned long B_MAX >
struct arithmetic< 0, B_MAX > {

enum { sum = B_MAX };

static
unsigned long inc ( unsigned long a ) {
return( B_MAX );
}

static
unsigned long add ( unsigned long a, unsigned long b ) {
return( b );
}

};
unsigned long add ( unsigned long a, unsigned long b ) {
return( arithmetic<100, 100>::add( a, b ) );
}

// end of file

Aug 21 '05 #7
Kai-Uwe Bux wrote:
Pattern (a)
template<typena me T, int a>
class Array {. . .};


Code Size depends on the number of different *types* (Classes) that you use
in your program. Since the instantiations of the Array<> template are
different classes the compiler will generate code for dealing with each of
them. That determines code size.


It seems to me that because of the "as-if" rule, the compiler
only needs to generate one function body and it can accept
the int as if it were a normal function parameter.

The C++ standard doesn't say that the compiler needs to
generate different blocks of code for different functions, eg:

void foo() { baz(); qux(); }
void bar() { baz(); qux(); }

A clever compiler/linker would only generate one block of code,
and calls to foo() and bar() would both go to it, assuming
that the program never tries to compare the addresses of
the two functions.

Aug 21 '05 #8
Old Wolf wrote:
Kai-Uwe Bux wrote:
Pattern (a)
template<typena me T, int a>
class Array {. . .};


Code Size depends on the number of different *types* (Classes) that you
use in your program. Since the instantiations of the Array<> template are
different classes the compiler will generate code for dealing with each
of them. That determines code size.


It seems to me that because of the "as-if" rule, the compiler
only needs to generate one function body and it can accept
the int as if it were a normal function parameter.


Agreed, the compiler is *allowed* to do that. And it will work in many
cases, but what about:

template < typename T, std::size_t N >
struct array {

T data [N];

...

}; //

Actually, I guess a compiler could actually handle this as a parametrized
allocation. Of course, calls to sizeof() would need to be handled
carefully. Anyway, I am too tired right now to think of something to really
force code generation for each instantiation. However, I would venture the
conjecture that most implementations will just mindlessly dump code for all
classes created.
Best

Kai-Uwe Bux

Aug 21 '05 #9

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

Similar topics

12
2777
by: Kristian Bisgaard Lassen | last post by:
Hi, How do I parameterize a template by a a allocated array of integers, which is declared static and constant, so I can make compile time optimizations depending on the content of the array. The way I have written my code makes g++ complain about it not being static. BTW I am new to the C++ language and also the templates it provides. Here is an example of what I want to do
7
2142
by: Lionel B | last post by:
Greetings. The following code compiles ok and does what I'd expect it to do: ---------- START CODE ---------- // test.cpp
2
2768
by: Siegfried Weiss | last post by:
Hi guys, i give up finding a solution by reading or by trial & error. Hope, YOU can help me! (Sorry for my rather long posting.) Stroustrup says, that templates could be declared with - type parameter, e.g. template<class T> - parameters with *simple* types like int, e.g. template<int size> - template parameter, e.g. template< template<class> class A > the latter beeing a type specifier, not an instance of A.
7
3175
by: icosahedron | last post by:
Is there a way to determine if a parameter to a function is a constant (e.g. 2.0f) versus a variable? Is there some way to determine if this is the case? (Say some metaprogramming tip or type trait?) I have a function with an if statement, that I would like to optimize away somehow. I was hoping the compiler would do it for me, but it doesn't seem to. Jay
1
3074
by: Andrzej 'Foxy' D. | last post by:
Hi! I cannot figure out, why is the following code incorrect: const int array = { 1 }; const int var = 1; template<int I> struct Blah {};
5
2277
by: StephQ | last post by:
This is from a thread that I posted on another forum some days ago. I didn't get any response, so I'm proposing it in this ng in hope of better luck :) The standard explanation is that pointer to functions are hard to inline for the compiler, and so you won't be able to avoid function call overhead. This is an important aspect when you are calling a function very frequently for evaluation reason: think of the problem of performing...
1
1801
by: Piet71 | last post by:
Hi, I have a stylesheet to select nodes from a source document via their "position" attribute. The template snippet is as follows: <xsl:template match="counter"> <xsl:if test="$number"><!--@pos=2 or @pos=5 or @pos=8 or @pos=11 or @pos=13 or @pos=15--> <xsl:copy-of select="."/> </xsl:if> </xsl:template>
2
2386
by: ndbecker2 | last post by:
On upgrading from gcc-4.1.2 to gcc-4.3, this (stripped down) code is now rejected: #include <vector> #include <iostream> template<typename T, template <typename Aclass CONT=std::vector> class Ring {
3
4772
by: Dan Smithers | last post by:
What constitutes a constant-expression? I know that it is something that can be determined at compile time. I am trying to use template code and keep getting compiler errors "error: cannot appear in a constant-expression" template <int s> class CFoo { private:
0
9944
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 usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9793
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11151
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10420
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 choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7974
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 instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7134
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5996
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4619
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
3
3238
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.