Контейнеры reference_wrappers (требуются операторы сравнения?) - PullRequest
1 голос
/ 10 апреля 2010

Если вы используете контейнеры stl вместе с reference_wrappers типов POD, код, подобный следующему, прекрасно работает:

int i = 0;
std::vector< boost::reference_wrapper<int> > is;
is.push_back(boost::ref(i));
std::cout << (std::find(is.begin(),is.end(),i)!=is.end()) << std::endl;

Однако, если вы используете не POD-типы, такие как (придуманный пример):

struct Integer
{
 int value;

 bool operator==(const Integer& rhs) const
 {
  return value==rhs.value;
 }

 bool operator!=(const Integer& rhs) const
 {
  return !(*this == rhs);
 }
};

Недостаточно объявить операторы сравнения выше, дополнительно вы должны объявить:

bool operator==(const boost::reference_wrapper<Integer>& lhs, const Integer& rhs)
{
 return boost::unwrap_ref(lhs)==rhs;
}

И, возможно, также:

bool operator==(const Integer& lhs, const boost::reference_wrapper<Integer>& rhs)
{
 return lhs==boost::unwrap_ref(rhs);
}

Чтобы заставить работать эквивалентный код:

Integer j = { 0 };
std::vector< boost::reference_wrapper<Integer> > js;
js.push_back(boost::ref(j));
std::cout << (std::find(js.begin(),js.end(),j)!=js.end()) << std::endl;

Теперь мне интересно, действительно ли это так, как это должно быть сделано, поскольку это несколько непрактично. Просто кажется, что должно быть более простое решение, например шаблоны:

template<class T>
bool operator==(const boost::reference_wrapper<T>& lhs, const T& rhs)
{
 return boost::unwrap_ref(lhs)==rhs;
}

template<class T>
bool operator==(const T& lhs, const boost::reference_wrapper<T>& rhs)
{
 return lhs==boost::unwrap_ref(rhs);
}

Вероятно, есть веская причина, почему reference_wrapper ведет себя так же, как и он (возможно, для размещения не POD-типов без операторов сравнения?). Может быть, уже есть элегантное решение, а я просто не нашел его.

1 Ответ

2 голосов
/ 10 апреля 2010

Работает ли приведенный выше пример, когда вы объявляете исходные процедуры сравнения такими:

friend bool operator==(const Integer& lhs, const Integer& rhs)
{
    return lhs.value == rhs.value;
}

friend bool operator!=(const Integer& lhs, const Integer& rhs)
{
    return !(lhs == rhs);
}

Обратите внимание, что объявление процедуры сравнения в классе - это не то же самое, что объявление процедуры сравнения функции-члена, поэтому они могут работать, а исходный код - нет.

...