【问题标题】:any_cast with std::any's and std::optional带有 std::any 和 std::optional 的 any_cast
【发布时间】:2016-10-06 14:48:50
【问题描述】:

如果我将T 放入std::any,我可以使用any_cast<T>(my_any) 得到它。但是标准(= C++17,目前处于投票阶段)是否包含像 any_cast<T>(optional<any> oa) 这样的函数,如果 oa 是 nullopt,则返回 nullopt,否则返回 std::any_cast<T>(oa.value())?或者类似的东西?

编辑:由于人们似乎在建议实现,我也将列出我现在使用的:

/* using magic here to select between boost/std::experimental/std versions */

template<typename T>
inline const optional<T> any_cast(const optional<any>& operand)
{
    return operand ? 
        optional<T>(any_cast<T>(operand.value())) :
        optional<T>(nullopt);
}

【问题讨论】:

    标签: c++ optional c++-standard-library c++17 stdany


    【解决方案1】:

    std::optional proposalstd::any proposal 中没有提及类似的内容。

    我认为使用延续函数来实现是微不足道的,因为返回类型根据可选对象的状态而有所不同:

    template <typename T, typename TOptional, typename TF>
    void any_cast_or_nullopt(TOptional&& o, TF&& f)
    {
        if(!o) return; 
        f(std::any_cast<T>(*o));
    }
    

    在适当的地方添加static_assert 和/或SFINAE 以约束函数。值*o 也应该根据o 的值类别转发。示例用法:

    int out = -1;
    
    std::optional<std::any> x;
    x = 10;
    
    any_cast_or_nullopt<int>(x, [&out](int value)
        {
            out = value;
        });
    
    assert(out == 10);
    

    【讨论】:

    • 我喜欢你的建议,但你真的需要 3 个模板参数吗?
    • 如果你想要正确性和灵活性,是的:T 用于any_castTOptional 用于完美转发可选值; TF 用于通用可调用对象。你可以在没有TOptional 的情况下实现它,但是当o 作为右值传递时,你需要重复代码才能正确移动*o
    • 但我没有 f。你强迫我将演员阵容与其结果的使用结合起来 - 这不像任何演员。
    • @einpoklum:您要求一个函数,该函数给出optional&lt;any&gt; 和模板参数T 返回T 实例或nullopt - 这是不可能的,因为T 和@ 987654342@ 是不相关的类型,因为 optional 的状态仅在运行时才知道。您可以让函数返回 optional&lt;T&gt; (如 Barry 建议的那样),或使用延续函数以便按照我的建议直接使用 T
    • 当然该函数应该返回一个可选的,这就是我返回 T 或 nullopt 的意思……但是好吧,我明白你为什么做了你所做的。你基本上实现了and_then
    【解决方案2】:

    如果std::optional 有一个bind(或and_then)成员函数(即optional&lt;T&gt; 上的一个函数,它接受T -&gt; optional&lt;U&gt; 并调用它或返回nullopt),那么就是这样您正在寻找:

    std::optional<std::any>> oa;
    
    optional<T> opt_t = oa.bind([](std::any& v) -> std::optional<T> {
        if (T* t = std::any_cast<T>(&v)) {
            return *t;
        }
        else {
            return std::nullopt;
        }
    });
    

    或者,如果你真的想直接调用any_cast&lt;T&gt;并处理抛出,map

    optional<T> opt_t = oa.map([](std::any& v) {
        return std::any_cast<T>(v);
    });
    

    std::optional 虽然没有延续函数,所以你必须把它们写成非成员函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-17
      • 2017-08-13
      • 1970-01-01
      • 2016-12-01
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多