Возвращаемое значение функции поиска, выполняющей поиск по вектору unique_ptr

#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 ). Если он используется только как ссылка на объект, то я согласен, возврат указателя выглядит лучше.