讓boost.variant支持lambda表達式訪問

此處輸入圖片的描述

前言

以前寫個過一篇博客叫《淺談boost.variant的幾種訪問方式》,裏面講到了能夠經過訪問者方式來獲取variant的值,可是在重載函數operator()裏面只可以獲取variant的值,若是要捕獲外部變量或調用外部函數比較麻煩,那麼有沒有一種方法來簡化variant的訪問呢?固然有,下面咱們讓variant支持lambda表達式訪問(我的博客也發表了《讓boost.variant支持lambda表達式訪問》)。ios

代碼

#include <iostream>
#include <string>
#include <utility>
#include <type_traits>
#include <boost/variant.hpp>

template<typename Function, typename... Args>
struct make_overload_impl : make_overload_impl<Function>::type, 
                            make_overload_impl<Args...>::type
{
    using type = make_overload_impl;
    using make_overload_impl<Function>::type::operator();
    using make_overload_impl<Args...>::type::operator();
    constexpr explicit make_overload_impl(Function&& func, Args&&... args)
        : make_overload_impl<Function>::type(std::forward<Function>(func)),
        make_overload_impl<Args...>::type(std::forward<Args>(args)...)
    {}
};

template<typename Function>
struct make_overload_impl<Function>
{
    using type = Function;
};

template<typename Return, typename... Args>
struct make_overload_impl<Return(*)(Args...)>
{
    using type = make_overload_impl;
    using Function = Return(*)(Args...);
    constexpr explicit make_overload_impl(const Function&& func) : _func(func) {}
    constexpr Return operator()(Args&&... args) const
    {
        return _func(std::forward<Args>(args)...);
    }

private:
    Function _func;
};

struct make_overload
{
    template<typename... Function, typename Overload = 
        typename make_overload_impl<typename std::decay<Function>::type...>::type>
    constexpr Overload operator()(Function&&... func) const
    {
        return Overload(std::forward<Function>(func)...);
    }
};

template<typename... Args>
auto make_visitor(Args&&... args)
{
    return make_overload()(std::forward<Args>(args)...);
}

int main()
{
    auto visitor = make_visitor
    (
        [](int& i) { std::cout << i << std::endl; },
        [](std::string& i) { std::cout << i << std::endl; }
    );
    boost::variant<int, std::string> v;
    v = "Hello world";
    boost::apply_visitor(visitor, v);
    v = 100;
    boost::apply_visitor(visitor, v);

    return 0;
}

該代碼也上傳到了個人githubgit

參考資料

讓BOOST.VARIANT的VISIT支持LAMBDAgithub

相關文章
相關標籤/搜索