Подтвердить что ты не робот

LibС++ vs libstdС++ std:: is_move_assignable: что является наиболее правильным?

Я пытаюсь получить более глубокое понимание С++, прочитав стандарт С++ 14 вместе с источником libС++ и libstdС++. Реализация различных элементов type_traits варьируется между двумя, особенно is_move_assignable, и я пытаюсь выяснить, какая из них "более правильная".

LibС++:

template <class _Tp> struct is_move_assignable
    : public is_assignable<typename add_lvalue_reference<_Tp>::type,
                           const typename add_rvalue_reference<_Tp>::type> {};

libstdС++:

template<typename _Tp, bool = __is_referenceable<_Tp>::value>
  struct __is_move_assignable_impl;

template<typename _Tp>
  struct __is_move_assignable_impl<_Tp, false>
  : public false_type { };

template<typename _Tp>
  struct __is_move_assignable_impl<_Tp, true>
  : public is_assignable<_Tp&, _Tp&&>
  { };

template<typename _Tp>
  struct is_move_assignable
  : public __is_move_assignable_impl<_Tp>
  { };

Стандартные состояния:

Для ссылочного типа T, тот же результат, что и is_assignable<T&, T&&>::value, иначе false.

Первое, что я заметил, это то, что libС++ применяет const ко второму параметру шаблона, что не кажется правильным, поскольку оператор присваивания переходов принимает неконстантное значение r. libstdС++ также использует __is_referenceable, который следует за формулировкой стандарта, но libС++ этого не делает. Это требование распространяется на использование libС++ add_lvalue_reference и add_rvalue_reference, которые обе обеспечивают __is_referenceable самостоятельно?

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

4b9b3361

Ответ 1

Для любой справки, две реализации выполняют одно и то же, поскольку посторонний const в libС++ бессмыслен, но и безвреден.

(Судя по различию, это, безусловно, выглядит как временное безумие для меня:) Кажется, проблема C & P из (неправильной) реализации is_copy_assignable.)

Для любых не ссылочных (т.е. cv void или отвратимых типов функций) libstdС++ возвращает false_type.

В libС++, add_{l,r}value_reference возвращает его без изменений (это зависит от разрешения проблемы, которое отправляет С++ 14). Поверхность const сверху ничего не делает для AFT и добавляет const для типов void y.

Затем переходим к is_assignable, который SFINAE-проверяет корректность declval<T>() = declval<U>() для T == U == some AFT или T == some void type и U = some const-qualified void type. Во всех случаях выражение плохо сформировано (с помощью SFINAE-friendly), поэтому мы получаем false_type назад.

Оба эквивалентны.

Ответ 3

__is_referenceable - нестандартная внутренняя процедура libstdС++. (Это не значит, что это плохо, просто я бы не ожидал, что libС++ будет использовать его). Кроме того, концепция "ссылочная" появилась гораздо позже is_move_assignable.

__is_referenceable помогает при работе с "отвратительными функциями"; такие вещи, как int (*) (double) &&.

Похоже, мне нужно написать больше тестов: -)