提升融合折叠带有lambda的参数包

时间:2015-08-07 21:39:07

标签: c++ templates boost lambda

在下面的代码中(C ++ 14,没有来自C ++ 17的'折叠'),我试图在编译时使用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...}, ...

1 个答案:

答案 0 :(得分:2)

由于您希望在编译时进行所有计算,boost::fusion::fold不是正确的工具。

相反,我会使用size中的offset计算constexprControlledLayout2

#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