Functor Parameters: Template vs. Members

W

woessner

Hi all. This isn't a really pressing question, but it has been kicking
around my head for a while. Is there any major difference between the
following functors:

template<typename T, T m_kTarget>
struct SEqual1
{
bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}
};

template<typename T>
struct SEqual2
{
Equal2(const T& krTarget): m_kTarget(krTarget) {}

bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}

private:
const T& m_kTarget;
};

Obviously, SEqual1 can't be used with non-primitive types. But beyond
that, is there any reason to prefer one over the other? I'm thinking
SEqual1 will run faster but may cause code bloat due to many
instantiations.

This is a pretty trivial example, but I've come across situations like
this a couple of times. I think I almost always go with SEqual2, but
I'm really starting to wonder if I should consider the alternative.

Thanks in advance,
Bill
 
A

amparikh

Hi all. This isn't a really pressing question, but it has been kicking
around my head for a while. Is there any major difference between the
following functors:

template<typename T, T m_kTarget>
struct SEqual1
{
bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}
};

template<typename T>
struct SEqual2
{
Equal2(const T& krTarget): m_kTarget(krTarget) {}

bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}

private:
const T& m_kTarget;
};

Obviously, SEqual1 can't be used with non-primitive types. But beyond
that, is there any reason to prefer one over the other? I'm thinking
SEqual1 will run faster but may cause code bloat due to many
instantiations.

This is a pretty trivial example, but I've come across situations like
this a couple of times. I think I almost always go with SEqual2, but
I'm really starting to wonder if I should consider the alternative.

Thanks in advance,
Bill

I think it is more like how you want to use the functor. I think
Vandevorrde's book has a pretty big section about the usage of functors
in this manner.

Having said that, if I want to preserve some state and possible that
state can change between calls to the function operator, then I would
use the second one.

First one might be better but as you pointed out causes a code bloat
for every value of that type you have uses it for.
 
V

Victor Bazarov

Hi all. This isn't a really pressing question, but it has been
kicking around my head for a while. Is there any major difference
between the following functors:

template<typename T, T m_kTarget>
struct SEqual1
{
bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}
};

template<typename T>
struct SEqual2
{
Equal2(const T& krTarget): m_kTarget(krTarget) {}

SEqual2 ...
bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}

private:
const T& m_kTarget;
};

Obviously, SEqual1 can't be used with non-primitive types. But beyond
that, is there any reason to prefer one over the other? I'm thinking
SEqual1 will run faster but may cause code bloat due to many
instantiations.

Why would it run faster? Yes, a use of an immediate value *could*
be better than a [reference to a] data member, but you have to prove
that (a) it's actually faster on your system and (b) that it matters
in the context of your program.
This is a pretty trivial example, but I've come across situations like
this a couple of times. I think I almost always go with SEqual2, but
I'm really starting to wonder if I should consider the alternative.

Even if you should, you wouldn't know by guessing. Only by measuring.

What you might consider is a specialisation of SEqual2 for integral
types. Bewhare, though, that you will only be able to use those with
literals. That alone is too severe a limitation for me.

V
 
V

Victor Bazarov

I think it is more like how you want to use the functor. I think
Vandevorrde's book has a pretty big section about the usage of
functors in this manner.

Having said that, if I want to preserve some state and possible that
state can change between calls to the function operator, then I would
use the second one.

The second one does not preclude the existence of state. It's the
manner in which it accepts the value against which to compare. The
former you have to instantiate using the template argument, the latter
you instantiate using the constructor argument.
First one might be better but as you pointed out causes a code bloat
for every value of that type you have uses it for.

If it's really as thin as the one presented here, does it matter?

V
 
E

Evan

template<typename T>
struct SEqual2
{
Equal2(const T& krTarget): m_kTarget(krTarget) {}

bool operator()(const T& krElem) const { return(krElem == m_kTarget);
}

private:
const T& m_kTarget;
};

Is there some reason that you're using a T reference instead of just a
T? Maybe just a holdover from wanting to be able to use that for
classtypes?

If you have reason to believe that SEqual would be faster, it might be
worth trying this as an option too; it'll probably be between the two.
(But as Victor said, don't just assume.)

Evan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top