Почему std :: allocator требует, чтобы значение атрибута duplicate_on_container_move_assignment было истинным?

Согласно текущему стандарту (20.7.9), std::allocator имеет член propagate_on_container_move_assignment, для которого установлено значение true_type:

распределитель классов шаблонов
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T * указатель;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef T value_type;
шаблон struct rebind {typedef allocator other; };
typedef true_type spread_on_container_move_assignment;
typedef true_type is_always_equal;
[...]

std::allocator не имеет элементов данных и всегда сравнивается как равный с любыми другими std::allocator. Есть ли причина перемещать эти распределители по умолчанию при назначении перемещения?


person user3514538    schedule 05.02.2017    source источник
comment
Это не C ++ 11. is_always_equal был добавлен после C ++ 14.   -  person Kerrek SB    schedule 05.02.2017


Ответы (1)


Я отвечаю относительно C ++ 11, как вы указали в теге:

Если бы свойство не соответствовало действительности, тогда в операциях присваивания потребовалось бы выполнить проверку времени выполнения на равенство распределителей. Да, конечно, распределители всегда будут равны, но код этого не знает и все равно должен будет выполнить проверку, и поэтому вы не можете предложить гарантию noexcept. С POCMA = true вы можете статически знать, что вы украдете ресурсы и, следовательно, не будете бросать.

C ++ 14 сделал std::allocator POCMA = true (в LWG2103) . Это было неверно в C ++ 11.

C ++ 17 представил новую черту is_always_equalN4258), чтобы разрешить спецификацию не генерирующих исключений для операций, даже если POCMA является ложным.

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

person Kerrek SB    schedule 05.02.2017
comment
Причина, по которой он был сделан POCMA, заключается в том, что он влияет на требования к элементам контейнера, а не только на спецификацию исключения. Без POCMA (или is_always_equal) вы должны учитывать возможность поэлементного перемещения. - person T.C.; 05.02.2017
comment
У меня есть следующий вопрос: почему бы не определить оператор constexpr ==? зачем эта покма нужна. Я мог бы предположить, что если бы я использовал такой оператор в качестве условия оператора if, удаление мертвого кода произвело бы тот же код, как если бы я использовал отправку тегов с POCMA no? - person Oliv; 05.02.2017
comment
@Oliv Возможен constexpr operator==, который обсуждается в lwg 2108. Чтобы использовать это, вам нужно попробовать сравнение равенства в контексте SFINAE, чтобы увидеть, является ли оно допустимым постоянным выражением (потому что не все распределители будут иметь constexpr operator==). Диспетчеризация тегов стала проще. Устранение мертвого кода по-прежнему работает для не-constexpr operator==, который всегда возвращает true. На практике это не имеет большого значения. - person Jonathan Wakely; 04.04.2017
comment
@JonathanWakely Спасибо за ответ. Хочу поделиться небольшим экспериментом. Я привыкаю программировать с концепцией TS с некоторого времени и, используя ее, я обнаружил, что большая часть моих дизайнерских решений была мотивирована трудностями, которые мне приходилось использовать и поддерживать код с помощью SFINAE. Вроде так и в STL. Я прочитал стандарт N4618: is_always_equal: true_type, только если выражение a1 == a2 гарантированно истинно для любых двух .... Это ненужное распространение ограничений для программиста распределителя. Это требование можно жестко запрограммировать. Почему бы не запрограммировать это жестко? - person Oliv; 05.04.2017
comment
@Oliv Я не понимаю вопроса (определение using is_always_equal = true_type; для распределителя делает жестко его кодирует), но я не думаю, что это место в комментарии здесь. Комментарии StackOverflow не обсуждаются. Придерживайтесь темы этого ответа. Задайте новый вопрос, если у вас есть вопросы. - person Jonathan Wakely; 05.04.2017
comment
@JonathanWakely Я думал, что компилятор действительно знает информацию, которую компилятор знает, но это может быть сложнее, чем я изначально думал. Чаще всего это дублирование кода (дублирование информации). Когда программист объявляет constexpr operator==, который всегда возвращает истину, компилятор получает информацию, которую is_always_equal должен предоставить еще раз. Это дублирование кода. Я не думаю, что C ++ нуждается во все большем и большем количестве правил. Для этого нужны способности к самоанализу кода. Концепция TS радикально улучшает код, но было бы лучше даже больше самоанализ. - person Oliv; 05.04.2017