template < class T >
class Array {
public:
T & operator[](int n) { return m_elements[n]; }
... // Other methods
private:
T m_elements;
}; Array< int > myIntArr; Array< unsigned int > myUnsignedIntAr; Array< int > and Array< unsigned int > both used by your program, we'll �wrap� one implementation within the other. First you declare your generic Array template which will handle Array<int> and then you declare a special cast version which will handle Array<unsigned int>.ntemplate < class T >
class Array {
public:
T & operator[](int n) { return m_elements[n]; }
... // Other methodsprivate:
T m_elements;
};
#define INTERNAL_TYPE int
#define EXTERNAL_TYPE unsigned int
template <>
class Array< EXTERNAL_TYPE > {
public:
inline EXTERNAL_TYPE & operator[](int n) { return (EXTERNAL_TYPE) m_array[n]; }
... // Other methods
private:
Array< INTERNAL_TYPE > m_array;
};
T, whereT is any given type. The type unsigned int is an exception though, because it sees that the template has been specialized to have a different implementation than the generic Array<T>. We actually utilize Array<T> from within Array<unsigned int> for the member data called m_array.inline request and therefore automatically map down any usage of Array<unsigned int> to actually be the exact same binary code asArray<int> when you do this.Array<T> might be amazingly complex or produce large amounts of CPU instructions during compiling. Regardless of how complex and large the implementation of Array<int> becomes, you can count on your inline cast specialization of each of Array's methods to add little or no code to your final binary application. #1 - fred.bertsch 2007-07-31 09:01 -
I don't know about GCC, but Microsoft's C compiler can perform what it calls "identical COMDAT folding". This looks through the generated object code and finds functions that are identical. It then merges them all together.
It sounds as though you're saying that this doesn't work, or perhaps you're saying that it doesn't work with another compiler?
Avoiding ugly code like what you've got above seems like a worthwhile thing to do. If you can do it with a simple compiler switch, then we'd be much better off.
#2 - fred.bertsch 2007-07-31 09:04 -
(That should say "Microsoft's C compiler".)
Here's a link to the docs: http://msdn2.microsoft.com/en-us/library/bxwfs976(vs.80).aspx
It's the /OPT:ICF switch, but it should be on by default.
#3 - Bender 2007-07-31 12:46 -
Fred's comment about identical COMDAT folding makes an important point. Some compiler / linker combinations are able to elimate duplicate code... sometimes. This isn't doable with all C objects and many times even data structures templated with plain old data (POD) data types cannot be "folded" into a unified set of code.
For example if you have a class called BigInteger which contains 64-bit integers and you also have a class called SmallInteger which contains 32-bit integers. The compiled binary code actually differs between an Array and Array. The described casting in the above article may be a good candidate for such a case (if you don't need to worry about byte alignments between elements of the array).
The BigInteger/SmallInteger situation in the above paragraph makes even more sense when you are making a 64-big program and you want all your structures to be 64-bit aligned in memory, thus speeding up access. (Unaligned data can dramatically hurt performance)
Hope you enjoyed the article... Look for a new article from me on eliminating C bloat within a few days!
#4 - John Connors said:
2007-08-01 08:34 -
Gcc (or rather ld) implements a similar mechanism via .linkonce directives. Multiple copies of the same code are emmited, and all but one is discarded at linktime.
#5 - Idetrorce 2007-12-15 02:58 -
very interesting, but I don't agree with you
Idetrorce
© 2010 PC-Doctor, Inc. | About this site | Contact | RSS | Back to top
Design by Andreas Viklund | Serendipity Template by Carl






