Re: question on pair in <utility>
On Feb 5, 4:49 am, Jeff Schwab <j...@schwabcenter.com> wrote:
James Kanze wrote:
On Feb 4, 5:45 am, Jeff Schwab <j...@schwabcenter.com> wrote:
subramanian10...@yahoo.com, India wrote:
Suppose left and right are two pair<T1, T2> objects.
Then
'left < right'
returns
left.first < right.first || !(right.first < left.first) && left.second=
< right.second.
Suppose left.first is NOT less than right.first.
Then isn't the subexpression '!(right.first < left.first)' equivalent
to 'left.first == right.first' ?
Not if one of the types involved doesn't define an operator==.
Is there any reason for mentioning like '!(right.first < left.first)'
instead of
'left.first == right.first' ?
operator< is generally the first operator defined for a given
type, since the standard containers and algorithms default to
std::less. operator==(a, b) is then defined as !(a < b) &&
!(b < a). Using operator< in the first place will therefore
tend to be a little more efficient.
For many types, an operator== can be implemented at far less
runtime cost than an operator<.
I didn't say it couldn't be, just that it often isn't.
That doesn't correspond to what I've actually seen in industry.
Most of the time, operator== gets implemented first, and the
relationship operators much later, only as needed, since for
most types, equality has meaning, but ordering doesn't. In the
end, operator< gets implement, if it does get implemented, with
arbitrary semantics, uniquely for the associative containers of
the STL.
And operator== can often be implemented significantly faster: on
a string, for example, you'll start by comparing the lengths.
operator== can be defined in terms of operator<, but the
reverse is not true; so, if you need both, you either have to
define operator== in terms of operator<, or you have to
implement them both manually and be careful to keep them in
sync.
Typically, both will be defined in terms of some named function:
compare(), or isEqual() (if there is a better algorithm for
equality). (Typically, one would hope, they will be implemented
using the Barton and Nackman trick, so all you have to do is
derived from the correct template instantiation, to get them
automatically.)
While the (typically) constant-factor speed-up *might* be
worth the increased risk of bugs, I would certainly wait for a
profiler to tell me so.
It's not a question of speed up:
bool operator==( MyType const& lhs, MyType const& rhs )
{
return lhs.compare( rhs ) == 0 ;
}
bool operator<( MyType const& lhs, MyType const& rhs )
{
return lhs.compare( rhs ) < 0 ;
}
The algorithm is in the compare() function, and will be equally
fast for both cases. (My own implementation of the
ComparisonOperators template base class uses a little bit of
meta programming to use isEqual() for == and !=, if it exists,
since if both isEqual and compare exist, compare will never be
slower.)
I don't think I've ever seen operator== implemented in terms of
operator<. I don't think it even occurs to most implementors to
do so.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34