Sign in to follow this  
dmatter

which is better: template or constructor parameters?

Recommended Posts

Which of the following is better (ie memory and speed trade-offs) Snippet 1 - using template parameter to pass a value
template <class T, T value>
struct ByTemplate
{
    vector<T> block;

    ByTemplate () : block(20, value) { }
    void MakeDefault (int pos) { block[pos] = value; }
};
---------- Snippet 2 - using constructor paramater to pass a value
template <class T>
struct ByConstructor
{
    vector<T> block;
    T value;

    ByConstructor (T cVal) : value(cVal), block(20, value) { }
    void MakeDefault (int pos) { block[pos] = value; }
};
This is just dummy code, what I actually want to do is keep a copy of T around for in-place construction, but the above does show what I;m asking. I think that Snippet1 is faster because value is around at compile time so it might allow optmizations to take place, it might also be better from the point of view that I don't have to store it within the class (as in Snippet2) but I'm not sure if the compiler would do this anyway (so no memory saved). wot does anyone think? Thanx in advance :)

Share this post


Link to post
Share on other sites
That doesn't seem like a performance bottleneck, not by a long shot, so the *much* greater flexibility offered by the constructor way would seem to be a better solution. Without knowing more about what the code is meant to do, it is hard to give any generally applicable advice.

If you are absolutely sure that a compile-time constant is enough now and in the future (refactoring afterwards will likely be a big pain in the butt), you could go the template way and use the constant-length array class from boost::array. But if you are even a bit unsure about the level of flexibility you might someday require, I'd recommend the more dynamic way.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
wot does anyone think?
Thanx in advance :)


I think that this is probably a horrible micro-optimization that will provide no noticeable speed benifit after much wasted time.

That said, which one is faster will depend entirely on wheither or not you're using a lot of different values or not. If you're only using one value, at worst, the first version won't be any slower. If you're using many values, the first version could be much slower due to the fact that a new version of each function will be created on most compilers for each value, causing more page misses and so forth when calling the function. That said, I suspect they will likely both preform EXACTLY the same and compile into the EXACT same code (in release mode, disregarding the symbol information), the constructor and so forth completely inlined to calls to vector.

In any case, the only definitive answer is to try both of them in a real life example (not some pansy ass benchmark, I'm talking about plug it in to your existing code that's having preformance problems in this area - if you don't have such code, you're prematurely optimizing, which is a waste of your time) and compare. When you can't tell a difference between the two, you'll know you've been wasting your time :-).

As such, I'd make my pick based on flexibility/what I wanted to do. Unless I'm doing some major template meta-programming, this would mean snippet 2 is best, since you can choose the value at runtime.

[Edited by - MaulingMonkey on June 9, 2005 3:39:37 PM]

Share this post


Link to post
Share on other sites
One problem with the template solution is that you will end up with different classes. For example, the first sample does not compile, but the second does.

ByTemplate< int, 1 > a;
ByTemplate< int, 2 > b;
a = b; // Oops!
ByTemplate< int, 1 > * p = &b; // Oops!

ByConstructor< int > a( 1 );
ByConstructor< int > b( 2 );
a = b; // Ok
ByConstructor< int > * p = &b; // Ok

In the end, the real question is this: Does the value of 'value' change the behavior of the class? If so, then you want separate classes, so it should be a template parameter. If not, it is just data and should not be a template parameter.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
One problem with the template solution is that you will end up with different classes. For example, the first sample does not compile, but the second does.

ByTemplate< int, 1 > a;
ByTemplate< int, 2 > b;
a = b; // Oops!
ByTemplate< int, 1 > * p = &b; // Oops!

ByConstructor< int > a( 1 );
ByConstructor< int > b( 2 );
a = b; // Ok
ByConstructor< int > * p = &b; // Ok

In the end, the real question is this: Does the value of 'value' change the behavior of the class? If so, then you want separate classes, so it should be a template parameter. If not, it is just data and should not be a template parameter.


template <class T, T value>
struct ByTemplate
{
vector<T> block;

ByTemplate () : block(20, value) { }
void MakeDefault (int pos) { block[pos] = value; }

vector< T > & value () { return block; }
const vector< T > & value () const { return block; }
operator vector< T > ( ) { return block; }
};


Share this post


Link to post
Share on other sites
Quote:
Original post by mgarriss
Quote:
Original post by JohnBolton
One problem with the template solution is that you will end up with different classes. For example, the first sample does not compile, but the second does.

ByTemplate< int, 1 > a;
ByTemplate< int, 2 > b;
a = b; // Oops!
ByTemplate< int, 1 > * p = &b; // Oops!

ByConstructor< int > a( 1 );
ByConstructor< int > b( 2 );
a = b; // Ok
ByConstructor< int > * p = &b; // Ok

In the end, the real question is this: Does the value of 'value' change the behavior of the class? If so, then you want separate classes, so it should be a template parameter. If not, it is just data and should not be a template parameter.


template <class T, T value>
struct ByTemplate
{
vector<T> block;

ByTemplate () : block(20, value) { }
void MakeDefault (int pos) { block[pos] = value; }

vector< T > & value () { return block; }
const vector< T > & value () const { return block; }
operator vector< T > ( ) { return block; }
};


You frogot to add a constructor so ByTemplate will be able to construct from such a vector. Even such a constructor will still not solve the p = &b case. The fact that you can do this also underscores the fact that the behavior dosn't really change the behavior of the class on a structural scale at all.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
You frogot to add a constructor so ByTemplate will be able to construct from such a vector. Even such a constructor will still not solve the p = &b case. The fact that you can do this also underscores the fact that the behavior dosn't really change the behavior of the class on a structural scale at all.

good points.

_ugly

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