在下面的代码中(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...}, ...
答案 0 :(得分:2)
由于您希望在编译时进行所有计算,boost::fusion::fold
不是正确的工具。
相反,我会使用size
中的offset
计算constexpr
和ControlledLayout2
:
#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