Что происходит с подвижным объектом, когда его вставка в std:: set терпит неудачу?
Что произойдет, если движимый объект, если я позвоню
std::set<>::insert
, и вставка не выполняется
потому что уже есть объект с тем же ключом, присутствующим в
набор. В частности, справедливо следующее:
struct Object
{
std::string key;
// ...
struct OrderByKey
{
bool operator()( Object const& lhs, Object const& rhs) const
{
return lhs.key < rhs.key;
}
};
Object( Object&& other )
: key(std::move(other.key))
// ...
{
}
};
и
std::set<Object, Object::OrderByKey> registry;
void
register(Object&& o)
{
auto status = registry.insert(std::move(o));
if (!status.second)
throw std::runtime_error("Duplicate entry for " + o.key);
}
После registry.insert
, когда вставка отсутствует, имеет
o
было перемещено или нет. (Если бы это могло быть перемещено, мне нужно
сохраните копию строки перед рукой, чтобы использовать ее в
сообщение об ошибке. (И да, я знаю, что я всегда могу написать:
throw std::runtime_error( "Duplicate entry for " + status->first.key );
Это то, что я, вероятно, сделаю. Но я все равно хотел бы знать
что стандарт говорит об этом.)
Ответы
Ответ 1
A std::move()
ed объект, переданный в стандартную библиотечную функцию, должен считаться перенесенным из: библиотека может считать объект своей единственной ссылкой, т.е. он может перейти от него, даже если он не используй это. Соответствующим пунктом является 17.6.4.9 [res.on.arguments] параграф 2, третий пул (он кажется идентичным в С++ 11 и С++ 14):
Если аргумент функции связывается с ссылкой на rvalue, реализация может предположить, что этот параметр является уникальной ссылкой на этот аргумент....
Ответ 2
Хорошо, чтобы ответить на ваш последний вопрос
Мне все равно хотелось бы знать, что говорится в этом стандарте
стандарт указывает, что произойдет с insert(t)
в Table 102 - Associative container requirements
, p717 из N3376 (выделение мое):
Требуется: если t является выражением non-const rvalue, value_type должен быть MoveInsertable в X; в противном случае value_type должен быть CopyInsertable в X.
Эффекты: Вставляет t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t. Компонент bool возвращенной пары является истинным тогда и только тогда, когда происходит вставка, и компонент итератора пары указывает на элемент с ключом, эквивалентным ключу t.
поэтому я бы сказал, что ничего не должно произойти и что ваш Object
по-прежнему действителен и не является неопределенным.
EDIT. Как заметил кто-то в комментарии, это может фактически зависеть от реализации, поскольку она явно требует, чтобы набор не был изменен, но не указывает на явное требование к аргументу и было ли оно перемещен или нет.
Ответ 3
Это (очень похоже на) LWG Активная проблема 2362, которая касается emplace. IIRC считает, что следует гарантировать, что объект перемещается только в том случае, если он вставлен/установлен. С emplace кажется, что это не так просто. Я не помню, легче ли вставить ситуацию.
Ответ 4
Третья пуля [res.on.arguments]/1 из N3936:
Если аргумент функции связывается с параметром ссылки rvalue, реализация может предполагать, что этот параметр является уникальной ссылкой на этот аргумент. [Примечание: если параметр является общим параметром формы T&&
и привязано значение l A
, этот аргумент привязывается к ссылке lvalue (14.8.2.1) и, таким образом, не покрывается предыдущим предложением. -end note] [Примечание. Если программа передает значение lvalue в значение x, передавая это lvalue библиотечной функции (например, вызывая функцию с аргументом move(x)
), программа эффективно запрашивает эту функцию для обработки этого lvalue как временный. Реализация бесплатна для оптимизации проверок псевдонимов, которые могут потребоваться, если аргумент был lvalue. -end note]
несмотря на то, что его лицо связано с псевдонимом, его можно интерпретировать как позволяющее реализации делать практически что угодно до аргумента, который передается стандартной библиотечной функции, связанной с ссылкой rvalue. Как Фабио говорит, бывают ситуации, когда ужесточение этой спецификации может быть полезно, и комитет смотрит на некоторые из них.