C++ 函数是否可以应用于std::optional的值,以获取可选值?

C++ 函数是否可以应用于std::optional的值,以获取可选值?,c++,stl,stdoptional,C++,Stl,Stdoptional,我认为将一个函数应用于一个可选函数是一个非常有用的模式。然而,与C++ STL相比,这是麻烦的。例如: std::optional<Vector3D> vec = tryCreateVector(); std::optional<float> length = vec.has_value() ? std::optional<float>(vec->length()) : std::nullopt; 据我所知,标准库不提供这种开箱即用的功能。不

我认为将一个函数应用于一个可选函数是一个非常有用的模式。然而,与C++ STL相比,这是麻烦的。例如:

std::optional<Vector3D> vec = tryCreateVector();
std::optional<float> length = 
    vec.has_value() ? std::optional<float>(vec->length()) : std::nullopt;

据我所知,标准库不提供这种开箱即用的功能。不过,实现它相当容易

#include <optional>
#include <iostream>
#include <functional>

std::optional<int> create_an_int()
{
    return 1;
}

std::optional<int> dont_create_an_int()
{
    return {};
}

template<typename T, typename F>
auto handler_wrapper(const std::optional<T>& in, F h)
{
    return in.has_value() ? std::optional{h(*in)} : std::nullopt;
}

int main()
{
    auto handler = [](const int& in){ return 3*in; };
    auto test = create_an_int();
    auto multiplied = handler_wrapper(test, handler);
    std::cout << *multiplied << std::endl;
    test = dont_create_an_int();
    auto nulled = handler_wrapper(test, handler);
    if (!nulled.has_value())
        std::cout << "null optional" << std::endl;
}
#包括
#包括
#包括
std::可选的create_an_int()
{
返回1;
}
std::可选的不创建一个int()
{
返回{};
}
模板
自动处理程序包装(常量标准::可选&in,F h)
{
返回in.has_value()?std::optional{h(*in)}:std::nullopt;
}
int main()
{
自动处理程序=[](常量int&in){return 3*in;};
自动测试=创建一个int();
自动倍增=处理器\包装器(测试,处理器);

std::cout您可以定义以下函数:

namespace detail
{
    template<typename Callable, typename T>
    struct apply_helper
    {
        using T_noref = typename std::remove_reference<T>::type;
        using value_type = typename T_noref::value_type;
        using Callable_return = decltype(std::declval<Callable>()(std::declval<value_type>()));
        using return_type = optional<Callable_return>;

        static return_type eval(Callable&& f, T&& val)
        {
            if(val)
            {
                return apply(std::forward<Callable&&>(f), *val);
            }
            else return boost::none;
        }

    private:
        static Callable_return apply(Callable&& f, value_type& v)
        {
            return f(v);
        }
        static Callable_return apply(Callable&& f, value_type const& v)
        {
            return f(v);
        }
        static Callable_return apply(Callable&& f, value_type&& v)
        {
            return f(v);
        }

    };
}
template<typename Callable, typename T> 
optional<decltype(std::declval<Callable>()(std::declval<T>()))> apply(Callable&& f, optional<T> const& a)
{
    return detail::apply_helper<Callable, optional<T> const&>::eval(std::forward<Callable>(f), a);
}
名称空间详细信息
{
模板
结构应用辅助程序
{
使用T_noref=typename std::remove_reference::type;
使用value\u type=typename T\u noref::value\u type;
使用Callable_return=decltype(std::declval()(std::declval());
使用返回类型=可选;
静态返回类型eval(可调用&f,T&&val)
{
if(val)
{
返回应用(标准::转发(f),*val);
}
否则返回boost::无;
}
私人:
静态可调用\返回应用(可调用&f,值\类型&v)
{
返回f(v);
}
静态可调用\返回应用(可调用和f,值\类型常量和v)
{
返回f(v);
}
静态可调用\返回应用(可调用(&f),值\类型(&v)
{
返回f(v);
}
};
}
模板
可选应用(可调用(&f),可选常量(&a)
{
返回细节::apply_helper::eval(std::forward(f),a);
}
然后可以像这样使用:

optional<int> foo(optional<int> value)
{
    auto f = [](int v){return v + 10;};
    return apply(f, value);
}
可选foo(可选值)
{
自动f=[](int v){返回v+10;};
返回应用(f,值);
}

不在标准中。我正在编写一个提供此类内容的库。对
boost
的引用是旧的C++17之前的代码的残余吗?是的,我用boost::optional原型化了它。使用
std::optional
您将使用
std::nullopt
optional<int> foo(optional<int> value)
{
    auto f = [](int v){return v + 10;};
    return apply(f, value);
}