472,354 Members | 2,150 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,354 software developers and data experts.

Which causes more code-bloat: inline virtual or template class?

Greetings!!

I introduced the so-called "thin-template" pattern for controlling the
code bloat caused due to template usage.

However, one of the functions in the template happens to be virtual as
well. To support thin-template, I need to make virtual function as
inline.

Now, I know that compiler would generate an out-of-line copy when it
takes the address of my inline virtual fucntion, thus making _two_
copies of this function : one out-of-line to be used by VTABLE, and one
inline for genuine inline substituions.

Doubts:

1. Is declaring a virtual function as inline a good design? Does it
indicate their is some flaw in my design? I have not seen much code
that makes a virtual function as inline too, and hence this doubt.

2. As a rule of thumb, who should cause more code bloat : normal
template or out-of-line function? I wanna know this /cuz if template
cuase more code bloat, I wanna keep my virtual as inline. ELse I remove
thin template and make my virtual as non-inline.
The below code should give some idea as to what I am doing:

class Base
{
public:
virtual int DoSomething() = 0;
protected:
Base();
};

class IntermediateBase : public Base
{
protected:
IntermediateBase(void* aSomeParam, void* aArg) :
iSomeParam(aSomeParam), iArgs(aArg) {}
virtual int DoSomething() = 0;
protected:
void* iSomeParam;
void* iArgs;
};
template <class TYPE, class INPUT>
class ConcreteClass : public IntermediateBase
{
typedef int (TYPE::*MemberFuncPtr)(const INPUT&);
public:
inline ConcreteClass(TYPE& aCommandType, INPUT& aArgumentsToCommand,
MemberFuncPtr aMFP)
: IntermediateBase( static_cast<TYPE*>(&aCommandType),
static_cast<INPUT*>(&aArgumentsToCommand) ),
iMFP(aMFP)
{
}

inline virtual int DoSomething() // VIRTUAL AND LINE - THIS CODE
SMELLS ROT?
{
return ( static_cast<TYPE*>(iSomeParam)->*ConcreteClass::iMFP )(
*(static_cast<INPUT*>(iArgs)) );
}
private:
MemberFuncPtr iMFP;
};

Aug 25 '05 #1
6 3854
RainBow wrote:
I introduced the so-called "thin-template" pattern for controlling the
code bloat caused due to template usage.
Could you maybe share your findings how much bloat you manage to control
and what problems eliminating the bloat helps to avoid? Thanks!
[..]


V
Aug 25 '05 #2
Please note: when I say "I introduced" - I did not mean I invented
it/discovered it. I learnt this pattern when working on Symbian. If you
google for "thin template", one of the first 5 search results should
take you to Symbian site.

Also, I am sorry, but I am _not_ doing this r&d currently - I just want
a tentative answer for this. I know that the answer depends how often
are you calling the Execute() call from what all compilation units -
and I forgot to mention that in my earlier question - its just that
this inline function will be called from atmost 2 or 3 compilation
units. So is the case with template instantiation (okay, its
obvious...). :-)

I will surely post my results in this group as and when I do that
activity - but right now, I just want a rough, tentative answer so that
I can finalise my design and proceed.

Thanks,
-Viren

Aug 25 '05 #3
RainBow wrote:
I introduced the so-called "thin-template" pattern
for controlling the code bloat caused due to template usage.

However,
one of the functions in the template happens to be virtual as well.
To support thin-template, I need to make virtual function as inline.

Now, I know that compiler would generate an out-of-line copy
when it takes the address of my inline virtual fucntion,
thus making _two_ copies of this function:
one out-of-line to be used by VTABLE and
one inline for genuine inline substituions.

Doubts:

1. Is declaring a virtual function as inline a good design?
Yes.
Does it indicate [that there] is some flaw in my design?
I have not seen much code that makes a virtual function as inline too
and hence this doubt.
This is improbable.
If you apply a virtual function to an object
in the scope where it was created,
the compiler knows the actual type of the object
and a good optimizing compiler will inline the virtual function.
2. As a rule of thumb, who should cause more code bloat:
normal template or out-of-line function?
I wanna know this because, if template cuase more code bloat,
I wanna keep my virtual as inline. Otherwise,
I remove thin template and make my virtual as non-inline.

The below code should give some idea as to what I am doing:

class Base {
protected:
Base(void);
public:
virtual int DoSomething(void) = 0;
};

class IntermediateBase: public Base {
protected:
void* iSomeParam;
void* iArgs;
IntermediateBase(void* aSomeParam, void* aArg):
iSomeParam(aSomeParam), iArgs(aArg) { }
virtual
int DoSomething(void) = 0;
};

template <class TYPE, class INPUT>
class ConcreteClass: public IntermediateBase {
private:
typedef int (TYPE::*MemberFuncPtr)(const INPUT&);
MemberFuncPtr iMFP;
public:
ConcreteClass(TYPE& aCommandType,
INPUT& aArgumentsToCommand, MemberFuncPtr aMFP):
IntermediateBase(static_cast<TYPE*>(&aCommandType) ,
static_cast<INPUT*>(&aArgumentsToCommand)), iMFP(aMFP) { }

virtual
int DoSomething(void) { // VIRTUAL AND LINE - THIS CODE SMELLS ROT?
return (static_cast<TYPE*>(iSomeParam)->*ConcreteClass::iMFP)
(*(static_cast<INPUT*>(iArgs)));
}
};
inline functions do *not* cause code bloat.
They exist simply
to discourage programmers who are concerned about performance
from inlining code manually.

I *always* define inline functions (and operators)
and I let the optimizing compiler decide
whether to actually inline them or not.

inline functions can increase compile time substantially.
You might consider taking advantage of both
inline *and* external function definitions:
cat file.h #ifndef GUARD_FILE_H
#define GUARD_FILE_H 1

#ifdef EFINE_INLINE
inline
double f(double x) {
return x*(x + 2.0) + 1.0;
}
#else //EFINE_INLINE
double f(double x);
#endif//EFINE_INLINE
#endif//GUARD_FILE_H
cat file.cc #undef EFINE_INLINE
#include "file.h"

double f(double x) {
return x*(x + 2.0) + 1.0;
}
g++ -DEFINE_INLINE -Wall -ansi -pedantic -O3 -c file.cc
nm --demangle file.o

00000000 T f(double)

This allows your inline and external function definitions
to coexist peacefully.
Use the -DEFINE_INLINE option only after you have finished
testing and debugging all of your code.
This will speed up the program development cycle
and allow you to optimize your code just before deployment.
Aug 25 '05 #4
RainBow wrote:
Greetings!!

I introduced the so-called "thin-template" pattern for controlling the
code bloat caused due to template usage.

However, one of the functions in the template happens to be virtual as
well. To support thin-template, I need to make virtual function as
inline.

Now, I know that compiler would generate an out-of-line copy when it
takes the address of my inline virtual fucntion, thus making _two_
copies of this function : one out-of-line to be used by VTABLE, and one
inline for genuine inline substituions.

Doubts:

1. Is declaring a virtual function as inline a good design? Does it
indicate their is some flaw in my design? I have not seen much code
that makes a virtual function as inline too, and hence this doubt.
I wouldn't say that declaring a function inline is part of a "design"
really - I suppose it could be called a "practice". And one that is
unlikely to make much of a difference to a virtual class method. To
inline a virtual function call, the exact type of the object involved
in the call must be unvarying and be known at compile time. Needless to
say, there are few occasions where a polymorphic reference can be only
one type, and the compiler can tell what its type must be. After all,
the whole point of polymorphism is that an object's type is determined
at runtime, based on the operating state of the program.
2. As a rule of thumb, who should cause more code bloat : normal
template or out-of-line function? I wanna know this /cuz if template
cuase more code bloat, I wanna keep my virtual as inline. ELse I remove
thin template and make my virtual as non-inline.
The below code should give some idea as to what I am doing:

class Base
{
public:
virtual int DoSomething() = 0;
protected:
Base();
};

class IntermediateBase : public Base
{
protected:
IntermediateBase(void* aSomeParam, void* aArg) :
iSomeParam(aSomeParam), iArgs(aArg) {}
virtual int DoSomething() = 0;
protected:
void* iSomeParam;
void* iArgs;
};
template <class TYPE, class INPUT>
class ConcreteClass : public IntermediateBase
{
typedef int (TYPE::*MemberFuncPtr)(const INPUT&);
public:
inline ConcreteClass(TYPE& aCommandType, INPUT& aArgumentsToCommand,
MemberFuncPtr aMFP)
: IntermediateBase( static_cast<TYPE*>(&aCommandType),
static_cast<INPUT*>(&aArgumentsToCommand) ),
iMFP(aMFP)
{
}

inline virtual int DoSomething() // VIRTUAL AND LINE - THIS CODE
SMELLS ROT?
{
return ( static_cast<TYPE*>(iSomeParam)->*ConcreteClass::iMFP )(
*(static_cast<INPUT*>(iArgs)) );
}
private:
MemberFuncPtr iMFP;
};


Template code "bloat" is measured not by the total amount of code
generated from instantiating templates (which can be considerable) but
rather by the amount of duplicated code from instantiating templates
with interchangeable types (from the template's perspective). For
instance if a class template accepts a pointer type as its type
parameter, but does nothing special depending on the type being pointed
to, then instantiating the template with a series of different pointer
types will "bloat" the program with essentially duplicated code. Some
compilers can detect duplicated code and "fold" the code into a single
set of instructions (leaving stubs for the "folded" routines since
template functions must each retain a unique address). Of course if the
compiler folds duplicate code then there is less incentive for the
programmer to avoid template bloat at the source code level.

In the code above, there seems to be little opportunity for template
bloat, since the class template seems quite type-specific. Furthermore
any optimization seems premature at this point, particularly if it
complicates the implementation.

I would instead write the program using the best design available and
then test the program first for correctness, and then for performance.
If performance (measured by the speed or the size of the program) turns
out to be inadequate at that point, then it is a good idea to start
looking for optimizations. The advantage of this approach is in that
case that the program turns out to be small and fast enough using the
optimal design, then no time would have been wasted making unneeded
optimizations that would have comprised the design. And in the case
that the program turns out not to b small or fast enough, then any
optimizations that are made start with a working program - meaning that
any bugs caused by subsequent changes will be much easier to track
down.

Greg

Aug 25 '05 #5
Thank you very much Greg for that beautiful information. Surely, I am
thinking about optimisation even before a single line of code is
written - while we are still in the design phase. I think I have been
too much scared of code size (at binary level of course) of a C++
program versus a C program. In the past, I was criticised for writing
too many classes when perhaps a few C functions would have done the
trick - keeping the program size extremely small (albeit at the cost of
increasing the maintenance efforts).

This time, I did not want to take any chances and be careful about the
estiamted program size right from beginning and hence these (silly??)
concerns. :-) But your posting has opened my eyes and I realise what a
bad approach I had been taking.

Thank you very much again.

Have a great day ahead!!

--V

Aug 25 '05 #6

RainBow wrote:
Thank you very much Greg for that beautiful information. Surely, I am
thinking about optimisation even before a single line of code is
written - while we are still in the design phase. I think I have been
too much scared of code size (at binary level of course) of a C++
program versus a C program. In the past, I was criticised for writing
too many classes when perhaps a few C functions would have done the
trick - keeping the program size extremely small (albeit at the cost of
increasing the maintenance efforts).

This time, I did not want to take any chances and be careful about the
estiamted program size right from beginning and hence these (silly??)
concerns. :-) But your posting has opened my eyes and I realise what a
bad approach I had been taking.

Thank you very much again.

Have a great day ahead!!

--V


Presumably you could have the linker generate a link map for the
program you want to make smaller. A link map would tell you how how
many functions were compiled into the binary and the size of each one.
Then you would only have to work to make the functions either smaller
or fewer or both.

I think that would be a more effective approach than asking the readers
of this newgroup which functions in your program to target.

Greg

Aug 25 '05 #7

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

Similar topics

10
by: Jupiter49 | last post by:
I'm trying to move pictures around on the screen, with a slight delay between the first picture and second picture (following onmousemove). When I add the setTimeout function I must be doing it...
6
by: nick | last post by:
i haven't learnt c++ before ,if i want to learn vc++,do i need to buy a c++ book to learn before i learn vc++? or some vc++ books are suitable to someone who hasn't learnt c++ before? any...
1
by: craigkenisston | last post by:
Microsoft's datarepeater sample causes warning in the IDE. Hi, The code here : ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/cpgenref/html/cpconrepeaterwebservercontrol.htm Causes the...
12
by: wizard04 | last post by:
I have a drop-down list, populated from a database, a few text boxes, and a few buttons on a page. The ddl is set to autopostback. For some reason, whenever a postback happens (when an item in...
11
by: tinman | last post by:
Hi... I have the following two excerpts from a method. It basically reads data from a DataReader and loads it in a collection. Excerpt A: ******** With ProjectData
31
by: Spiro Trikaliotis | last post by:
Hello, I have a question regarding subtracting a pointer from another one. Assume I have two pointers p1 and p2, which both point to a memory area obtained with malloc(). Assume p1 = p2 + some...
15
by: Rob Meade | last post by:
Hi all, I have a databse which I'm pulling the data from for my ASP page. I have 4 tables, Course, Feature, Objective, and PreRequisite. The last three all contain a course product code and a...
7
by: semut | last post by:
Given that the string is of null-terminated type. What could be the possible causes (by experience) the string to have no null character (\0) and cause buffer overflow later. I know it is quite...
10
by: jimmy | last post by:
Hi again, sorry for posting two questions so close together but im working on a school project which is due in soon and running into some difficulties implementing the database parts. I have the...
15
by: tom | last post by:
why delete the dynamically allocated memory twice causes an error, see the code below: int _tmain(int argc, _TCHAR* argv) { int *pi = new int(12); cout<<*pi; delete pi; delete pi; }
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made but the http to https rule only works for...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. header("Location:".$urlback); Is this the right layout the...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and...
0
by: Arjunsri | last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and credentials and received a successful connection...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
0
by: Carina712 | last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand. Background colors can be used to highlight important...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
0
by: Rahul1995seven | last post by:
Introduction: In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...

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.