|
Boost : |
From: Eric Friedman (ebf_at_[hidden])
Date: 2003-08-30 19:43:38
Dirk,
Dirk Schreib wrote:
> I would like a variant to be LessThanComparable if all
> BoundedTypes are LessThanComparable.
I've actually been working on this on and off for some time. I have not
committed anything to CVS though because I have found that defining
relational operators for variant that are always meaningful is unfortunately
tricky, and perhaps impossible (see below).
> In this example
>
> typedef boost::variant<T1, T2, ..., TN> V;
> V v1 = T1( x );
> V v2 = T2( y );
> V v3 = T1( z );
>
> v1 < v2 should always be true. And v1 < v3 should be the same as T1( x ) <
> T1( z ).
For starters, I agree that v1 < v3 should be the same as x < y.
I'm not so sure about v1 < v2, though. I'm inferring that you believe that
operator< should be implemented as follows:
template <typename T1, ..., typename TN>
bool operator<(
const variant<T1,...,TN>& lhs,
, const variant<T1,...,TN>& rhs
)
{
if (lhs.which() == rhs.which())
... // compare using underlying operator<
else
return lhs.which() < rhs.which()
}
While this certainly solves the problem of storing variants in associative
containers by establishing an ordering, the ordering is rather arbitrary and
potentially confusing. Consider the following:
typedef variant<int, double> var;
bool result1 = int(3) < double(2.0); // false
bool result2 = var(3) < var(2.0); // true
On first glance, IMO most users would expect result1 == result2. With your
ordering scheme, this would be untrue. Unfortunately, I do not believe the
problem is specific to your ordering scheme.
Ultimately, I do not believe any ordering scheme will provide meaningful,
straightforward semantics. Assuming I am correct, I propose that the variant
library offer your ordering scheme -- but only as an explicit comparison
function, calling it variant_less. This would allow, for instance:
std::set< my_variant, boost::variant_less<my_variant> >
I'd appreciate feedback.
Thanks,
Eric
P.S. The issue of equality comparison between variants is a bit more
straightforward. However, we still have the following potentially confusing
situation:
typedef variant<int, double> var;
bool result3 = (int(3) == double(3.0)); // true
bool result4 = (var(3) == var(3.0)); // false
Thus, perhaps a boost::variant_equal comparison function is also in order.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk