5

我怀疑 boost::optional's已被弃用,因为如果将右值作为参数get_value_or传递它是不安全的。default但是,能够引用可选值或默认替代值有时会很有用。

以下安全吗?

template<typename T>
T const& get_reference_or(boost::optional<T> const& opt, T const& alt)
{
    if (opt) return opt.get();
    else return alt;
}

template<typename T>
T const& get_reference_or(boost::optional<T> const&, T&&) = delete;
4

1 回答 1

3

如所写,您的代码在类型推导方面存在问题,因为T可以从两个参数中推导出来。但是假设您实际上T只从可选项中推导出来:

template <class T>
struct NonDeducedHelper { using type = T; };

template <class T>
using NonDeduced = typename NonDeducedHelper<T>::type;

template<typename T>
T const& get_reference_or(boost::optional<T> const& opt, NonDeduced<T> const& alt)
{
    if (opt) return opt.get();
    else return alt;
}

template<typename T>
T const& get_reference_or(boost::optional<T> const&, NonDeduced<T>&&) = delete;

然后,代码几乎是安全的,因为当使用非const右值作为 的默认值时get_reference_or,它将尝试使用已删除的重载并且无法编译。但是,为了 100% 安全,您还应该删除右值的重载const

template<typename T>
T const& get_reference_or(boost::optional<T> const&, NonDeduced<T> const&&) = delete;
于 2018-04-17T08:18:08.877 回答