2015-02-06 2 views
1

подталкивание :: вариант определяет оператор < следующим образом:Как изменить поведение наддува :: оператор вариант <

Если который() == rhs.which() затем: content_this < content_rhs, где content_this - это содержимое * this и content_rhs - это содержимое rhs. В противном случае: which() < rhs.which().

Это не то, что я хочу, потому что я хотел бы провалить сравнение <. Например, если у меня есть вариант, как это:

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

Я хочу DataType (1) < DataType (2,0), чтобы добиться успеха, но DataType (1) < DataType ("2"), чтобы бросить исключение. Есть ли способ достичь этого?

я не могу определить

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

, потому что он будет конфликтовать с оператором члена <, определенной в варианте класса.

Я могу определить static_visitor, но я хотел бы знать, есть ли способ перегрузить оператора <.

+1

Независимо от того, что вы используете, эти сравнения должны иметь необязательный настраиваемый компаратор. – chris

+1

К сожалению 'вариант :: operator <' является функцией-членом. – sbabbi

ответ

1

Хотя упаковка ваш DataType внутри другой структуры, безусловно, является лучшим решением, иметь в виду, что если вам нужен быстрый и грязный исправить это работает:

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

В C++ 11 вы должны быть в состоянии избежать namespace boost.

Обратите внимание, что это нарушит ODR, если только ваш TU не увидит эту специализацию, прежде чем использовать ее.

+0

спасибо, это работает для меня.Однако мне нужно увеличить пространство имен, используя gcc 4.8 – swang

1

Создайте struct, содержащий только boost::variant<Ts...> v;. Передвиньте его конструкторы (возможно, некоторые из них вручную). Предоставьте operator boost::variant<Ts...>() опционально.

У вас есть < на этом struct.

Обратите внимание, что boost::variant предназначен для нормализации соединения. Предполагается, что нормальный что некоторые variant s являются одним типом, а некоторые - другим.

< обычно находится в контейнерах типа std::map или при сортировке. Если ключи будут вынуждены быть одного типа, или отсортированные элементы, которые будут одного типа, кажутся плохой идеей. variant не должен содержать оба типа, если не ожидается, что такой variant будет содержать оба типа.

Места, где < автоматически используется, имеют тенденцию ожидать дополнительного объекта предиката заказа. Я лично не могу придумать, почему я когда-либо использовал исключение, бросая предикатный объект вручную, что заставляет меня лишить вас возможности по умолчанию.