which is better: template or constructor parameters?

Started by
7 comments, last by mgarriss 18 years, 10 months ago
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 :)
Advertisement
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.
i don't really see any advantage to snippet 2 unless you won't know what value you want until runtime.
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]
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.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
John,

Good observation and nicely worded. A+.
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
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; }};


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.
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

This topic is closed to new replies.

Advertisement