在下面的代码中(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...}, ...
最佳答案 由于您希望在编译时进行所有计算,因此boost :: fusion :: fold不是正确的工具.
相反,我会使用ControlledLayout2中的constexpr计算大小和偏移量:
#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