Sign in to follow this  
discman1028

Is member function of templated class shared?

Recommended Posts

Hi, Let's say I had:
template <typename T, int I>
class foo
{
  void bar()
  {
   std::cout << m_member2 << std::endl;
  }

  int m_member2;
  T m_member[I];
};

And I created a ton of these... foo<int, 10> a; foo<float, 11> b; foo<double, 440> c; ... Would there only be one implementation of bar(), or would the code bloat to three implementations even if not _technically_ necessary? More specifically, is this an optimization that compilers typically make? I know the type of 'this' will be different depending on the template parameters, and as 'this' is typically passed as a hidden parameter to non-static member functions, there should be multiple versions... but for all intents and purposes, in this case 'this' could be a void* and one bar() implementation could be shared among all foo<T,I> class types. Just hoping to stimulate some discussion... I'm not anything more than curious. :)

Share this post


Link to post
Share on other sites
The compiler has to create 3 different instances, as they're 3 entirely different classes. If one considers template specialisation, they might even have entirely different source code for different template parameters.
However, what is finally written to the executable image may be a different story, that's very implementation dependent. I wouldn't count on it, but it is of course possible for a sufficiently intelligent compiler/linker suite to collapse many binary-identical functions into one. But like I said, that's implementation dependent.

Depending on the model, the compiler might even create many more than just 3 instances (one for every instantiation in every compilation unit) which are later merged by the linker. That would be what's called the "Borland model" which for example g++ uses by default (but can be told to do differently too).

Share this post


Link to post
Share on other sites
One strategy might be to use "template hoisting": move bar into a non-templated base class.

For example, nodes in linked list may be implemented like this:

struct NodeBase
{
NodeBase* next;
NodeBase* prev;

//some member functions that don't rely on the type of node contents
};

template <class T>
struct Node : public NodeBase
{
T data;

//member functions that rely on the template parameter
};


Share this post


Link to post
Share on other sites
#include <iostream>

template < typename T, int I >
struct Foo {
void bar() {
std::cout << quux << '\n';
}

T baz[ I ];
int quux;
};

int main() {
Foo< int, 10 > a;
Foo< float, 11 > b;
Foo< double, 440 > c;

a.quux = 13;
b.quux = 42;
c.quux = 92;

a.bar();
b.bar();
c.bar();
}




I compiled the above code on GNU GCC 4.3.0 and looked at the assembly output. It effectively generates this:
int main() {
std::cout << 13 << '\n' << 42 << '\n' << 92 << '\n';
}
Given that you need to define Foo::bar in a header anyway, it should be very easy for the compiler to inline it, even for more complicated definitions of bar, if feasible.

Share this post


Link to post
Share on other sites
Quote:
Original post by discman1028
More specifically, is this an optimization that compilers typically make?

On recent versions of MSVC, you can enable the /OPT:ICF linker option (identical COMDAT folding) and the linker will mush together functions that have identical machine code. I don't know if any other linkers have equivalent behavior.

Incidentally, using this option can make debugging a release build extremely confusing.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by discman1028
More specifically, is this an optimization that compilers typically make?

On recent versions of MSVC, you can enable the /OPT:ICF linker option (identical COMDAT folding) and the linker will mush together functions that have identical machine code. I don't know if any other linkers have equivalent behavior.

Incidentally, using this option can make debugging a release build extremely confusing.

It isn't that confusing once you know about it. It is +very+ confusing when you are surprised by the effect! :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this