使用对齐符展开参数包的语法是什么?

What is the syntax for parameter pack expansion with alignas?

本文关键字:语法 是什么 参数 对齐      更新时间:2023-10-16

我试图在对齐说明符中展开参数包。我的语法不对。下面是一个简单的例子:

#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])说"带有省略号的对齐说明符是一个包扩展",所以看起来应该可以做我想做的事情。

我一直无法找到这种参数包扩展的示例,并且我搜索gcc中可能存在的错误也没有找到任何东西。

这看起来像GCC中的bug c++/59012,在GCC 5.2中修复了。你的例子在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的建议中改编的,使用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);

语法正确;自5.2.0以来,GCC仅在对齐说明符内实现包扩展。59012 - alignas不支持参数包扩展

你可以尝试使用alignas (std::aligned_union_t<1, Ts...>),但不幸的是gcc从5.1.0开始只实现了aligned_union,所以它只是稍微好一点。

如果你想使用旧的编译器,你必须自己编写constexpr max函数(因为旧版本的gcc也不实现constexpr max(std::initializer_list<T>))并自己计算最大对齐,如alignas(max({alignof(T)...}))