itisamos 2024-01-26 15:50 采纳率: 100%
浏览 13
已结题

c++14的新特性,如何改写回退到c++11

RPC工程中使用前同事的代码,其使用C++14特性,但是工程环境仅支持c++11,因此编译不过,完整的function_handler.h如下:

#pragma once

#include <string>
#include <map>
#include <functional>
#include <initializer_list>
using std::string;

#include <dsserialize/data_stream.h>

class FunctionHandler
{
public:
    FunctionHandler() {}
    ~FunctionHandler() {}

    template <typename F>
    void bind(const string & name, F func);

    void call(const string & name, DataStream & in, DataStream & out);

private:
    template <typename F>
    void wrap(F func, DataStream & in, DataStream & out);

    template <typename R, typename ...Args>
    void wrap_impl(R(*func)(Args...), DataStream & in, DataStream & out);

    template <typename R, typename ...Args>
    void wrap_impl(std::function<R(Args...)> func, DataStream & in, DataStream & out);

    template<typename R, typename F, typename Tuple>
    typename std::enable_if<std::is_same<R, void>::value, int32_t>::type
    call_impl(F func, Tuple args);

    template<typename R, typename F, typename Tuple>
    typename std::enable_if<!std::is_same<R, void>::value, R>::type
    call_impl(F func, Tuple args);

    template<typename R, typename F, typename Tuple>
    auto invoke(F && func, Tuple && t);

    template<typename R, typename F, typename Tuple, std::size_t... Index>
    auto invoke_impl(F && func, Tuple && t, std::index_sequence<Index...>);

    template<typename Tuple, std::size_t... I>
    Tuple get_args(DataStream & ds, std::index_sequence<I...>);

    template<typename Tuple, std::size_t Id>
    void get_arg(DataStream & ds, Tuple & t);

private:
    std::map<string, std::function<void(DataStream &, DataStream &)>> m_handlers;
};

inline void FunctionHandler::call(const string & name, DataStream & in, DataStream & out)
{
    auto func = m_handlers[name];
    func(in, out);
}

template <typename F>
void FunctionHandler::bind(const string & name, F func)
{
    m_handlers[name] = std::bind(&FunctionHandler::wrap<F>, this, func, std::placeholders::_1, std::placeholders::_2);
}

template <typename F>
void FunctionHandler::wrap(F func, DataStream & in, DataStream & out)
{
    wrap_impl(func, in, out);
}

template <typename R, typename ...Args>
void FunctionHandler::wrap_impl(R(*func)(Args...), DataStream & in, DataStream & out)
{
    wrap_impl(std::function<R(Args...)>(func), in, out);
}

template <typename R, typename ...Args>
void FunctionHandler::wrap_impl(std::function<R(Args...)> func, DataStream & in, DataStream & out)
{
    using args_type = std::tuple<typename std::decay<Args>::type...>;
    constexpr auto size = std::tuple_size<typename std::decay<args_type>::type>::value;
    args_type args = get_args<args_type>(in, std::make_index_sequence<size>{});
    auto ret = call_impl<R>(func, args);
    out << ret;
}

template<typename R, typename F, typename Tuple>
typename std::enable_if<std::is_same<R, void>::value, int32_t>::type
FunctionHandler::call_impl(F func, Tuple args)
{
    invoke<R>(func, args);
    return 0;
}

template<typename R, typename F, typename Tuple>
typename std::enable_if<!std::is_same<R, void>::value, R>::type
FunctionHandler::call_impl(F func, Tuple args)
{
    return invoke<R>(func, args);
}

template<typename R, typename F, typename Tuple>
auto FunctionHandler::invoke(F && func, Tuple && t)
{
    constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
    return invoke_impl<R>(std::forward<F>(func), std::forward<Tuple>(t), std::make_index_sequence<size>{});
}

template<typename R, typename F, typename Tuple, std::size_t... Index>
auto FunctionHandler::invoke_impl(F && func, Tuple && t, std::index_sequence<Index...>)
{
    return func(std::get<Index>(std::forward<Tuple>(t))...);
}

template<typename Tuple, std::size_t... I>
Tuple FunctionHandler::get_args(DataStream & ds, std::index_sequence<I...>)
{
    Tuple t;
    std::initializer_list<int>{((get_arg<Tuple, I>(ds, t)), 0)...};
    return t;
}

template<typename Tuple, std::size_t Id>
void FunctionHandler::get_arg(DataStream & ds, Tuple & t)
{
    ds >> std::get<Id>(t);
}

模板元编程有难度,因此请教如何改写并保留其功能,使其c++11下能编译通过?
主要就是std::index_sequence 和 std::make_index_sequence的c++14新特性问题吧。

  • 写回答

8条回答 默认 最新

  • flower980323 2024-01-26 16:25
    关注
    namespace std {
    template<class _Ty,
        _Ty... _Vals>
        struct integer_sequence
    {    // sequence of integer parameters
        static_assert(is_integral<_Ty>::value,
            "integer_sequence<T, I...> requires T to be an integral type.");
    
        typedef integer_sequence<_Ty, _Vals...> type;
        typedef _Ty value_type;
    
        static constexpr size_t size() _NOEXCEPT
        {    // get length of parameter list
            return (sizeof...(_Vals));
        }
    };
    
    template<bool _Negative,
        bool _Zero,
        class _Int_con,
        class _Int_seq>
        struct _Make_seq
    {    // explodes gracefully below 0
        static_assert(!_Negative,
            "make_integer_sequence<T, N> requires N to be non-negative.");
    };
    
    template<class _Ty,
        _Ty... _Vals>
        struct _Make_seq<false, true,
        integral_constant<_Ty, 0>,
        integer_sequence<_Ty, _Vals...> >
        : integer_sequence<_Ty, _Vals...>
    {    // ends recursion at 0
    };
    
    template<class _Ty,
        _Ty _Ix,
        _Ty... _Vals>
        struct _Make_seq<false, false,
        integral_constant<_Ty, _Ix>,
        integer_sequence<_Ty, _Vals...> >
        : _Make_seq<false, _Ix == 1,
        integral_constant<_Ty, _Ix - 1>,
        integer_sequence<_Ty, _Ix - 1, _Vals...> >
    {    // counts down to 0
    };
    
    template<class _Ty,
        _Ty _Size>
        using make_integer_sequence = typename _Make_seq < _Size < 0, _Size == 0,
        integral_constant<_Ty, _Size>, integer_sequence<_Ty> >::type;
    
    template<size_t... _Vals>
    using index_sequence = integer_sequence<size_t, _Vals...>;
    template<size_t _Size>
    using make_index_sequence = make_integer_sequence<size_t, _Size>;
    template<class... _Types>
    using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
    
    }
    

    直接源码加到项目里面去,把这段代码放到类定义前面,如有帮助请采纳,谢谢

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(7条)

报告相同问题?

问题事件

  • 系统已结题 2月3日
  • 已采纳回答 1月26日
  • 创建了问题 1月26日

悬赏问题

  • ¥30 求解达问题(有红包)
  • ¥15 请解包一个pak文件
  • ¥15 不同系统编译兼容问题
  • ¥100 三相直流充电模块对数字电源芯片在物理上它必须具备哪些功能和性能?
  • ¥30 数字电源对DSP芯片的具体要求
  • ¥20 antv g6 折线边如何变为钝角
  • ¥30 如何在Matlab或Python中 设置饼图的高度
  • ¥15 nginx中的CORS策略应该如何配置
  • ¥30 信号与系统实验:采样定理分析
  • ¥100 我想找人帮我写Python 的股票分析代码,有意请加mathtao