我正在尝试在对齐说明符中扩展参数包。我无法正确理解语法。这是一个简单的例子:
#include <cstdint>
#include <tuple>
template <typename... Ts>
struct C
{
using Tuple_Type = std::tuple <Ts...>;
void f()
{
uint8_t i1;
uint8_t i2 alignas (2);
uint8_t i3 alignas (typename std::tuple_element<0, Tuple_Type>::type);
uint8_t i4 alignas (Ts...);
}
};
//template class C <>; // not compatible with i3 declaration above
template class C <uint64_t>;
无法使用gcc 4.8.3编译
foo.cpp: In member function 'void C<Ts>::f()':
foo.cpp:14:31: error: expected ')' before '...' token
uint8_t i4 alignas (Ts...);
^
foo.cpp:14:31: error: expected ')' before '...' token
foo.cpp:14:31: error: expected initializer before '...' token
C ++标准([dcl.align])说“带有省略号的 alignment-specifier 是一个包扩展”,所以看起来应该可以做我想要的。< / p>
我一直无法找到这种参数包扩展的示例,我在gcc中搜索可能的错误没有找到任何内容。
答案 0 :(得分:1)
你的语法是正确的; gcc仅在5.2.0之后的alignment-specifier中实现pack扩展。以下是错误: 59012 - alignas does not support parameter pack expansions 。
您可以尝试使用alignas (std::aligned_union_t<1, Ts...>)
,但遗憾的是,自5.1.0以来,gcc仅实现了aligned_union
,所以它只是略好一点。
如果您想使用较旧的编译器,您必须编写自己的constexpr max
函数(因为旧版本的gcc不会实现constexpr max(std::initializer_list<T>)
)和计算您自己的最大对齐方式为alignas(max({alignof(T)...}))
。
答案 1 :(得分:1)
这看起来像GCC中的bug c++/59012,已在GCC 5.2中修复。您的示例compiles fine与Clang 3.5.1。
值得注意的是,如果您完全省略省略号,GCC会正确地抱怨参数包:
14 : error: parameter packs not expanded with '...':
uint8_t i4 alignas(Ts);
^
你无法(轻松)将其与GCC 4.8.x合作;它太愚蠢了。但是,使用GCC 4.9及更高版本,您可以使用以下构思,我从ecatmur's suggestion改编为使用constexpr max
。
template<int...>
struct maxInts {};
template<int A, int B, int... Cs>
struct maxInts<A, B, Cs...> {
const static int value = A > B ? maxInts<A, Cs...>::value : maxInts<B, Cs...>::value;
};
template<int A, int B>
struct maxInts<A, B> {
const static int value = A > B ? A : B;
};
template<int A>
struct maxInts<A> {
const static int value = A;
};
这使您可以在编译时获得任意数量的整数,如:
const int x = maxInts<1, 2, 3, 4, 5>::value; // x == 5
现在你麻烦的alignas
看起来像这样:
uint8_t i4 alignas(maxInts<alignof(Ts)...>::value);