Reputation: 958
Is it an acceptable pattern to return a moved function parameter in case some kind of problem occurred? For example when trying to store data in a database, but validation failed and the data handle should be returned.
class Database {
using data_ptr = std::unique_ptr<std::vector<int>>;
public:
[[nodiscard]] std::expected<void, data_ptr>
validate_and_store(data_ptr&& data) {
if(!validate_data(data)) {
return std::unexpected(std::move(data));
}
m_data = std::move(data);
return {};
}
private:
data_ptr m_data;
static bool validate_data(data_ptr& data) {return data->size() < 6;}
};
The r-value parameter of validate_and_store
should indicate that ownership of the data is usually transferred, but in an unexpected case, a handle to the that data is returned.
So a consumer could use this as
Database db;
auto data_owner = get_big_data_from_somewhere();
auto db_info = db.validate_and_store(std::move(data_owner));
if(!db_info) {
data_owner = std::move(db_info.error());
}
Is there a better (or best) practice on how to intend giving up ownership on success, but returning it to the caller if a problem arises? Of course, one could just use a (non-const) reference here and just check for nullptr
afterwards, but that doesn't seem to show the intended behavior in a clear way.
Upvotes: 2
Views: 80