使用alignas进行参数包扩展的语法是什么?

时间:2015-08-04 15:08:57

标签: c++ c++11 gcc

我正在尝试在对齐说明符中扩展参数包。我无法正确理解语法。这是一个简单的例子:

#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中搜索可能的错误没有找到任何内容。

2 个答案:

答案 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);

Here's a working example.