swang
swang

Reputation: 5239

How to change the behaviour of boost::variant operator <

boost::variant defines operator < as follows:

If which() == rhs.which() then: content_this < content_rhs, where content_this is the content of *this and content_rhs is the content of rhs. Otherwise: which() < rhs.which().

This is not what I want, because I'd like to fail some < comparison. For example, if I have a variant like this:

typedef boost::variant<int, double, std::string> DataType;

I want DataType(1) < DataType(2.0) to succeed but DataType(1) < DataType("2") to throw exception. Is there any way to achieve this?

I can't define

bool operator < (const Field& lhs, const Field& rhs)

because it will conflict with member operator < defined in variant class.

I can define a static_visitor, but I'd like to know if there's anyway to overload operator <.

Upvotes: 1

Views: 204

Answers (2)

sbabbi
sbabbi

Reputation: 11181

While wrapping yourDataType inside another struct is surely the best solution, keep in mind that if you need a quick and dirty fix this works:

namespace boost
{
template<>
bool DataType::operator<(const DataType &) const
{   
    // impl
}
}

In C++11 you should be able to avoid the namespace boost.

Notice that this will break the ODR unless all your TU see this specialization before actually using it.

Upvotes: 1

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275270

Create a struct containing nothing but a boost::variant<Ts...> v;. Forward your constructors to it (possibly some manually). Provide an operator boost::variant<Ts...>() optionally.

Have your own < on this struct.

Note, however, that boost::variant is intended to normalize the union. It is supposed to be normal that some variants are one type, and some are another type.

< is usually in std::map type containers or when sorting. Having the keys be forced to be all the same type, or the sorted elements to be all the same type, seems like a bad idea. The variant shouldn't contain both types if it isn't expected for any such variant to contain both types.

The places where < is automatically used all tend to expect an optional ordering predicate object. I personally cannot think of why I'd ever use an exception throwing predicate object manually, which makes me leery of making yours the default.

Upvotes: 1

Related Questions