【问题标题】:Is alignas legal when used for an inline static member?用于内联静态成员时对齐是否合法?
【发布时间】:2020-06-15 19:22:05
【问题描述】:

alignasinline static 成员变量一起使用而 Clang 不使用时,MSVC 会引发错误。哪一个是正确的? clang 的标志:-O2 -std=c++2a。 MSVC 的标志:/std:c++latest

错误:

错误 C2024:“alignas”属性仅适用于变量、数据成员和标签类型

#include <iostream> //https://godbolt.org/z/q4ScM7
#include <atomic>
#include <random>
class PRNG {
public:
    alignas(128) inline static std::atomic<uint64_t> state{ [] {
        auto rd{ std::random_device{} };
        return static_cast<uint64_t>(rd()) << 32
            | static_cast<uint64_t>(rd());
    }() };
};

int main()
{
    std::cout << PRNG::state;
}

以下变体,其中初始化与定义分开并且不使用inline,两者都成功:

#include <iostream> //https://godbolt.org/z/rvq6AP
#include <atomic>
#include <random>
class PRNG {
public:
    alignas(128) static std::atomic<uint64_t> state;
};
alignas(128) std::atomic<uint64_t> PRNG::state{ [] {
    auto rd{ std::random_device{} };
    return static_cast<uint64_t>(rd()) << 32
        | static_cast<uint64_t>(rd());
}() };

int main()
{
    std::cout << PRNG::state;
}

inline static 不是成员变量时,两者都接受alignas

#include <iostream> //https://godbolt.org/z/Kd9NEV
#include <atomic>
#include <random>

alignas(128) inline static std::atomic<uint64_t> state{ [] {
    auto rd{ std::random_device{} };
    return static_cast<uint64_t>(rd()) << 32
        | static_cast<uint64_t>(rd());
}() };

int main()
{
    std::cout << state;
}

【问题讨论】:

    标签: c++ visual-c++ clang c++17 language-lawyer


    【解决方案1】:

    在 C++17 [dcl.align]/1 中它说:

    对齐说明符可以应用于变量或类数据成员,但不能应用于位字段、函数参数或异常声明。

    在您的代码中,state 是数据成员(静态数据成员是数据成员),因此允许使用对齐说明符。

    所以我建议报告编译器错误。

    【讨论】:

    • 另请注意 Ahmed 的回答:此错误仅限于 /std:c++latest。使用 /std:c++17,代码可以工作。
    【解决方案2】:

    在 MSVC 2019 中,std:c++latest 指的是最新工作草案中的预览功能,我认为它仍然存在问题。 所以你应该使用 std:c++17 并且它会编译没有错误。 /std

    /std:c++latest 选项启用当前在编译器和库中实现的后 C++17 语言和库功能。这些功能可能包括 C++20 工作草案的更改、C++17 中未包含的缺陷更新以及标准草案的实验性提案。有关受支持的语言和库功能的列表,请参阅 Visual C++ 的新增功能。 /std:c++latest 选项不启用由 /experimental 开关保护的功能,但可能需要启用它们。

    【讨论】:

    • 非常有趣。所以这是一个回归,因为它适用于 /std:c++17。
    • 也许,我更喜欢在 std20 发布之前使用 std17
    猜你喜欢
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 2015-05-12
    • 2015-01-02
    • 1970-01-01
    • 2016-05-03
    相关资源
    最近更新 更多