#c #c 11 #vector #iterator #unique-ptr
#c #c 11 #вектор #итератор #уникальный-ptr
Вопрос:
Я ищу по вектору unique_ptr для объекта. Объект разрешается, например, пользователем, вводящим имя. Следовательно, функция вида:
std::unique_ptr<obj> constamp; objectForName(std::string name) {
std::vector<std::unique_ptr<obj>>::iterator it;
it = std::find_if(objVec.begin(), objVec.end(), [name](const std::unique_ptr<obj>amp; object) -> bool {return object->getName() == name; });
if (it != objVec.end())
return *it;
else
throw(Some_Exception("Exception message"));
}
Я хотел бы повторно использовать эту функцию в случае добавления объекта в этот вектор. Функция должна вызывать это и в случае, если она не найдена, возвращать что-то, что может быть проверено вызывающей функцией, вместо того, чтобы выдавать исключение. Вызывающая функция может вызвать исключение при проверке возвращаемого значения. Мой вопрос в том, что может быть возвращено, чтобы вызывающая функция могла быть проверена?
Комментарии:
1. Поскольку кажется, что
object
не может владетьnullptr
, вы можете вернутьobj*
вместо этого, и поэтому возвращаетесьnullptr
, когда не найдены.
Ответ №1:
Просто верните указатель:
obj const* objectForName( std::string constamp; name )
{
std::vector<std::unique_ptr<obj>>::iterator results
= std::find_if(
objVec.begin(),
objVec.end(),
[amp;]( std::unique_ptr<obj> constamp; object ) {
return object->getName == name; } );
return results != objVec.end()
? results->get()
: nullptr;
}
Комментарии:
1. Хорошо, но при возврате необработанного указателя: разве это не противоречит парадигме интеллектуальных указателей?
2. @worker11811 не владеющие необработанными указателями не приветствуются. Вызывающий объект не становится владельцем объекта pointee, так что все в порядке.
3. А если для объекта вызывается delete?
4. Если у вас болит голова, когда вы бьетесь ею о стену, перестаньте биться головой о стену, и она перестанет болеть. Использование
delete
— это именно то, что противоречит «парадигме интеллектуальных указателей», а не это.5. Я это знаю. Дело в том, что я это знаю. Кто-то другой, который использует код после меня, видит необработанный указатель и удаляет его. Так не является ли смысл использования необработанного указателя снова частью проблемы, которую интеллектуальные указатели пытаются исправить?
Ответ №2:
Вы также можете использовать что-то вроде boost::optional
here:
boost::optional<std::unique_ptr<obj> constamp;> objectForName(std::string name);
std::vector<std::unique_ptr<obj>>::iterator it;
it = std::find_if(objVec.begin(), objVec.end(), [name](const std::unique_ptr<obj>amp; object) -> bool {return object->getName() == name; });
if (it != objVec.end())
return *it;
else
return boost::none;
}
Использование:
const auto val = objectForName("bla1");
if (val) std::cout << "ok: " << val.get()->getName();
else std::cout << "none";
Комментарии:
1. Спасибо, очень признателен. Есть идеи о том, как это сделать без использования библиотеки boost? Я бы предпочел сделать это с помощью стандартной библиотеки.
2. @worker11811 gcc 4.9 и clang имеет
experimental/optional
заголовок. Я думаю, что это почти то же самое, что и boost. Но это экспериментальное расширение. Может быть, вы можете просто скопировать и вставить его в свой проект, там не так много кода..3. Поэтому мы должны использовать
boost::optional
со ссылкой, а не с указателем. Это звучит как дополнительная сложность ни для чего. (Много, много лет назад я рассматривал возможность расширения своегоFallible
класса для поддержки создания экземпляров по ссылочным типам и решил, что это глупо, поскольку все, что он мог бы сделать, это обернуть указатель. В случаеboost::optional
с , это еще более глупо, потому что интерфейсboost::optional
разработан для имитации интерфейса указателя. Наboost::optional
самом деле в документации об этом говорится: «стандартный» необязательный тип — это указатель.)4. @JamesKanze Ну, это исходный код с минимальными изменениями. Может быть, есть какая-то большая идея, почему эта функция возвращает ссылку unique_ptr (например, она использует unique_ptr
get_deleter
). Если он используется только как ссылка на объект, то я согласен, возврат указателя выглядит лучше.