C ++, что такое идиоматический способ избежать указателей? - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть метод, который принимает const ref к набору. Я хочу назвать это и м.б. передать набор к нему. Если у меня есть это. Итак, сначала я вижу, есть ли у меня набор:

const auto& it = mapOfSets.find("token");
if (it != std::end(mapOfSets)) {
  myFunction(it.second);
} else {
  MySetType emptySet;
  myFunction(emptySet);
}

Что такое идиоматический способ сделать это? Мне не нравится вышеупомянутое, потому что вызов myFunction повторяется дважды, и есть несколько других аргументов, поэтому есть некоторое ненужное дублирование кода.

Программист на C во мне просто хочет изменить функцию так, чтобы она принимала указатель и передавала nullptr, если set не найден, но я чувствую, что C ++ теперь избегает указателей? ..

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

Если вы напишите вспомогательную функцию для поиска набора на карте, вы можете вернуть ссылку на специальный пустой набор в случае, если вы ничего не нашли:

const MySetType& find(const MyMapType& mapOfSets, const std::string& key) {
    auto it = mapOfSets.find(key);
    if (it != std::end(mapOfSets)) {
        return it->second;
    }
    static const MySetType emptySet;
    return emptySet;
}

Тогда ваш код вызова просто:

myFunction(find(mapOfSets, "token"));
0 голосов
/ 07 ноября 2018

Может быть рукописный optional_reference, который может ссылаться на nullptr, но будет throw при разыменовании и не имеет дополнительных bool

#include <stdexcept>
#include <memory>

class null_access_exception: public std::logic_error
{
    using base = std::logic_error;
public:
    null_access_exception():
        base("Try to dereference null optional_reference!")
    {}
};

template <class Ptr_t>
class optional_reference
{
    using self = optional_reference;
    using reference = decltype(*std::declval<Ptr_t>());
    Ptr_t ptr = nullptr;

public:
    optional_reference() = default;
    optional_reference(const self&) = default;

    self& operator = (const self&) = delete;

    template <class U>
    constexpr optional_reference(U &&obj) noexcept: 
        ptr(std::addressof(obj))
    {}

    constexpr explicit operator bool() const noexcept
    { return has_value(); }

    constexpr bool has_value() const noexcept
    { return ptr != nullptr; }

    constexpr auto& value() const
    {
        if (!has_value())
            throw null_access_exception();

        return *ptr;
    }

    template <class U>
    constexpr auto& value_or(U &&obj) const noexcept
    {
        if (has_value())
            return *ptr;
        else
            return reference(std::forward<U>(obj));
    }
};

, а затем

  1. Измените myfunction, чтобы он принимал optional_reference, а затем проверьте его.

  2. Оберните, как показано ниже.

    constexpr const static auto null_set (); void Myfunction (опциональный_wrapper ref) { MyFunction (ref.value_or (null_set)); }

0 голосов
/ 06 ноября 2018

Вы можете использовать условный оператор:

myFunction(it != mapOfSets.end() ? it->second : MySetType{});

Я не думаю, что есть идиоматический способ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...