C++:Boost.MPL 等效于在类型 vector 中的第 i 个类型上调用函数

标签 c++ templates boost template-meta-programming boost-mpl

我设计了这样一个函数:

template<template<class> class TMapper, class TResult = void, class TUserContext>
static typename TResult mapParam(int index, TUserContext ctx)

它需要一个TMapper,它需要符合以下概念:

template<class T> struct Mapper { static TResult map(int index, TUserContent ctx) {} }

Mapper 类型为每个参数实例化一次,但“map”函数仅针对给定索引处的参数调用。 Mapper 使用参数的类型 (T) 进行参数化。在测试中,我们希望能够对一个我们甚至不知道存在的参数做一些事情,并且仍然使用它的精确类型,但不需要在真实的测试用例中添加任何模板元编程...

有没有办法通过 Boost.MPL 做到这一点,以便阅读这段代码的人不需要理解它,而可能只需要使用 boost 知识,或者至少在这里有更详细的文档?

这里是完整的代码(T::TParams 是一个任意函数参数类型的 boost::mpl::vector<>):

template<template<class> class TMapper, class TResult = void, class TUserContext>
        static typename TResult mapParam(int index, TUserContext ctx) {
            return mapParamInternal<TMapper, TResult, boost::mpl::size<T::TParams>::value - 1>(index, ctx);
        }

template<template<class> class TMapper, class TResult, int CurrentIndex, class TUserContext>
static typename boost::enable_if_c<CurrentIndex >= 0, TResult>::type mapParamInternal(int targetIndex, TUserContext ctx) {
    if(CurrentIndex == targetIndex) {
        return TMapper<
            typename boost::mpl::at<
                T::TParams, 
                boost::mpl::int_<CurrentIndex>
            >::type>::map(targetIndex, ctx);
    } else {
        return mapParamInternal<TMapper, TResult, CurrentIndex - 1>(targetIndex, ctx);
    }
}

template<template<class> class TMapper, class TResult, int CurrentIndex, class TUserContext>
static typename boost::disable_if_c<CurrentIndex >= 0, TResult>::type mapParamInternal(int targetIndex, TUserContext ctx) {
    UNREFERENCED_PARAMETER(targetIndex);
    UNREFERENCED_PARAMETER(ctx);
    return TResult();
}

举例说明这可能有什么用:

template<class TParam>
struct UpdateParameter {
    static void map(int index, CallSerializerTest<T>* self) {
        self->trace.updateParameter(
            TCallSig::getParamName(index), 
            TypeUpdatedValue<TParam>::get());
    }
};

void updateParameter(int index) {
    updatedParams.push_back(index);
    TCallSig::mapParam<UpdateParameter>(index, this);
}

上面的代码将调用“self->trace.updateParameter”一次,对于“index”给出的参数,“TParam”将具有该参数的正确类型。 “TCallSig”是定义了“mapParam”函数的任意调用签名。我们通过谷歌测试类型参数化测试获得了大量的签名。我认为这是一个非常酷的系统,一旦您掌握了元编程的窍门,它就会使测试用例非常简洁且易于阅读。

最佳答案

检查 Boost.Fusion图书馆。该库旨在充当编译时和运行时世界之间的桥梁,提供使用两个世界属性的功能和算法。
该库具有函数式不可变 spirit ,并提供类似于函数式语言(如 map、fold 等)的算法。但关键是 Fusion 具有在此类构造中使用编译时属性的能力(感谢 MPL) .例如(从介绍中提取):

template <typename Sequence>
void xml_print_pointers(Sequence const& seq)
{
    for_each(filter_if<boost::is_pointer<_> >(seq), print_xml());
}

如您所见,仅当该元素是指针(它是元素类型的编译时属性)时,它才会对运行时 序列的每个元素执行操作。

我相信您可以使用这些结构轻松实现您的算法。

关于C++:Boost.MPL 等效于在类型 vector 中的第 i 个类型上调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25113725/

相关文章:

c++ - Boost C++ - 搜索 spirit 符号表

c++ - 使用 Boost::Asio 进行双向 TCP 通信的程序结构

c++ - 如何从 Spirit::Qi 规则访问 boost::variant 成员?

头文件 LNK2019 中的 C++ API 实现

c++ - C++ 中的模板参数

c++ - 使用 << 的整数运算

c++ - 如何创建采用 wstring 的派生类并调用采用字符串的基类构造函数?

c++ - 类崩溃编译器中的 MSVC 2010 模板化映射

c++ - 每当使用 constexpr 指定调用的函数时,将委托(delegate)方法声明为 constexpr

c++ - 如何返回映射到可变参数位置的类型