c++ - Boost fusion 使用 lambda fold 参数包

标签 c++ templates boost lambda

在下面的代码中(C++14,C++17 中没有“fold ”),我试图在编译时使用 boost fusion fold、参数包自动计算类字段的固定偏移量和一个 lambda 。不幸的是,这会导致编译时错误......是否可以这样做?

[编辑:其他事情也困扰着我:这不是我想要的。我希望 ControlledLayout2 的 _size 在编译时可用(这就是我将其设为静态的原因),而不仅仅是在调用构造函数时可用]

template <typename T, uint32_t size>
struct Field2
{
    typedef T _type;
    static const uint32_t _size;
    static uint32_t _offset;
};

template <typename T, uint32_t size>
const uint32_t Field2<T,size>::_size = size;

template <typename T, uint32_t size>
uint32_t Field2<T,size>::_offset = 0;

template <typename ... T>
struct ControlledLayout2
{
    static uint32_t _size;

    ControlledLayout2(T... args) {
      _size = fold({args...}, 0, 
                   [&](uint32_t s, T field) { return T::_offset = s + T::_size; }...);
    };
};

...
ControlledLayout2<Field2<int, 32>, Field2<char, 1>, Field2<long, 64>> cl;
cout << cl._size << endl;
...

编译错误是:

error: parameter not expanded with '...';
_size = accumulate({args...}, ...

最佳答案

由于您想在编译时进行所有计算,boost::fusion::fold 不是适合此操作的工具。

相反,我会在 ControlledLayout2 中使用 constexpr 计算 sizeoffset:

#include <iostream>
#include <tuple>

template <typename T, uint32_t Size>
struct Field2
{
    using type = T;
    static const uint32_t size = Size;
};

template <typename T, typename U>
struct selector;

template <typename T, std::size_t... Is>
struct selector<T, std::index_sequence<Is...>>
{
    using type = std::tuple<typename std::tuple_element<Is, T>::type...>;
};

template <std::size_t N, typename... Ts>
struct remove_last_n
{
    using Indices = std::make_index_sequence<sizeof...(Ts)-N>;  
    using type = typename selector<std::tuple<Ts...>, Indices>::type;
};

template <typename ... Ts>
struct ControlledLayout2 
{    
    static constexpr uint32_t get_size()
    {
        return size_impl<Ts...>();
    }

    template <typename X, typename... Xs>
    static constexpr uint32_t size_impl(typename std::enable_if<(sizeof...(Xs) > 0)>::type* = 0)
    {
        return ((X::size) + size_impl<Xs...>());
    }

    template <typename X>
    static constexpr uint32_t size_impl()
    {
        return X::size;
    }

    template <std::size_t field_number>
    static constexpr uint32_t offset()
    {
        using Tuple = typename remove_last_n<sizeof...(Ts)-field_number, Ts...>::type;
        return offset_impl(Tuple{});
    }

    template <typename... Xs>
    static constexpr uint32_t offset_impl(std::tuple<Xs...>)
    {
        return size_impl<Xs...>();
    }

    static const uint32_t size = get_size();
};

int main()
{
    using Layout  = ControlledLayout2<Field2<int, 32>,
                                      Field2<char, 1>,
                                      Field2<char, 128>,
                                      Field2<long, 64>
                                      >;
    std::cout << Layout::size << std::endl;
    std::cout << Layout::offset<3>() << std::endl;
}

输出

225
161

live on coliru

关于c++ - Boost fusion 使用 lambda fold 参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31887033/

相关文章:

c++ - 如何使用 const 值初始化 const 对象的非常量属性?

templates - Golang 从模板访问设置

python - 与boost.python和python3的链接失败

c++ - 在编译时生成 BitCount LUT

c++ - 带 boost 的大整数:太大而无法以任何整数类型表示

c++ - 使用自定义比较函数设置构造函数

c++ - 使用 OpenSSL 的 AES 256-cbc 加密 C++

c++ - 学习DirectX需要具备哪些知识

c++ - 为什么必须在何处以及为什么要放置"template"和"typename"关键字?

c++ - 检测在编译时是否存在默认构造函数