std :: back_inserter нуждается в const_reference на старых GCC.Зачем? - PullRequest
5 голосов
/ 10 ноября 2011

В настоящее время я смотрю на некоторый код, который можно скомпилировать в более новых версиях GCC, но не в более старых. В моем случае я использую от std::back_inserter до std::copy некоторых данных из одной структуры данных в пользовательскую структуру данных. Однако, если я забуду определение типа typedef value_type & const_reference в этой пользовательской структуре данных, оно не будет скомпилировано в GCC 4.4. Тот же код компилируется и прекрасно работает на GCC 4.5.

Какая разница между этими двумя версиями компилятора, которая заставляет код компилироваться в одной версии, но не в другой. Я предполагаю, что это как-то связано с реализацией C ++ 11, которая была гораздо менее полной в GCC 4.4. Наверное, что-то с decltype или другим новым ключевым словом C ++ 11, я бы предположил.

Также корректен ли этот код, если я использую std::back_inserter без определения типа const_reference? Я обычно думал, что нужно реализовать полный набор typedefs (value_type, reference, const_reference и т. Д.), Чтобы быть совместимым с библиотекой STL-алгоритмов? Или я могу с уверенностью предположить, что если мой код компилируется в этом случае, я не вызываю ничего опасного (например, семантику перемещения, которая может разрушить мою другую структуру данных).

Ответы [ 2 ]

6 голосов
/ 10 ноября 2011

Стандарт (1998) гласит, что std::back_insert_iterator необходимо Container::const_reference. В «24.4.2.1 Шаблонный класс back_insert_iterator», [lib.back.insert.iterator], написано:

back_insert_iterator<Container>&
operator=(typename Container::const_reference value);

Стандарт 2011 хочет только Container::value_type,

back_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
back_insert_iterator<Container>&
operator=(typename Container::value_type&& value);

Итак, чтобы быть совместимым с обеими версиями стандарта C ++, определите как value_type, так и const_reference_type.

В GCC 4.4.6 и 4.5.1 определение operator= идентично (libstdc++-v3/include/bits/stl_iterator.h):

  back_insert_iterator&
  operator=(typename _Container::const_reference __value)
  {
    container->push_back(__value);
    return *this;
  }

и я получаю одинаковую ошибку с обоими компиляторами, возможно, вам придется перепроверить, используете ли вы правильные версии компилятора.

1 голос
/ 10 ноября 2011

Причина, по которой вам нужно const_reference, определена для вашей структуры данных, заключается в том, что оператор присваивания в GCC 4.4 для типа аргумента lvalue в классе std::back_insert_iterator определяется как:

template<class Container>
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
                  (typename Container::const_reference value);

Таким образомconst_reference должен быть разрешаемым идентификатором в вашем типе класса, чтобы правильно создать экземпляр оператора присваивания в шаблоне класса std::back_insert_iterator.

В GCC 4.5 это определение оператора присваивания для аргументов lvalue былоизменено на

template<class Container>
back_insert_iterator<Container>&
back_insert_iterator<Container>::operator=
                 (const typename Container::value_type& value);

для поддержки новой спецификации C ++ 11.Поскольку ваш код правильно компилируется с GCC 4.5, я предполагаю, что вы должны правильно определить value_type для вашей структуры данных.

...