【问题标题】:C++ what is the idiomatic way to avoid pointers?C++ 避免指针的惯用方法是什么?
【发布时间】:2018-11-06 20:49:35
【问题描述】:

我有一个将 const ref 带入集合的方法。我想叫它和 m.b.将一组传递给它。如果我有的话。所以首先我看看我是否有一套:

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

这样做的惯用方式是什么?我不喜欢上面的,因为对 myFunction 的调用重复了两次,并且还有一些其他参数,所以有一些不必要的代码重复。

我的 C 程序员只想更改函数以接受指针并在未找到 set 时传递 nullptr,但我觉得 C++ 现在都是为了避免指针?..

【问题讨论】:

  • it.second的类型是MySetType吧?
  • 是的,希望是
  • C++ 是关于避免原始 拥有 指针。像引用一样使用指针仍然可以。
  • 您可以创建一个返回 optional<reference_wrapper<const T>> 的助手进行查找并使用其 value_or 函数。但是,如果没有对引用的本机支持,那就有点尴尬了。
  • @NathanOliver 有些人还建议避免使用原始的非拥有指针,因为在阅读作者知道并遵循建议以避免原始拥有指针的代码时,这通常不是一个安全的假设

标签: c++ coding-style


【解决方案1】:

可以使用条件运算符:

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

我不认为有一种惯用的方式。

【讨论】:

  • 至少这是干燥的
【解决方案2】:

如果您编写了一个辅助函数来查找地图中的集合,那么您可以在没有找到任何内容的情况下返回对特殊空集合的引用:

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"));

【讨论】:

  • 这很难看,但我喜欢。
【解决方案3】:

可能是手写的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(); 无效我的功能(可选_包装器参考) { 我的函数(ref.value_or(null_set)); }

【讨论】:

    猜你喜欢
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 2016-09-25
    • 2013-02-25
    • 2017-02-18
    相关资源
    最近更新 更多