如何防止 GCC 为静态成员生成防护

wim*_*aan 5 c++ static gcc g++ compiler-optimization

以下是一个有时生成警卫有时不生成的最小示例:

struct A {
    inline A(int v = 0) {} // without ctors, guards are omitted
    int m1() const {
        return m;
    }
private:
    int m = 0;
};

//namespace { // without anon-ns guards are generated 
    template<typename T>
    struct X {
        static int foo() {
            // static T m; // even as local-static and -fno-threadsafe-statics, guards are generated 
            return m.m1();
        }
        inline static T m; // comment this and uncomment above to try as local-static
    };
//}

int main() {
    return X<A>::foo();    
}
Run Code Online (Sandbox Code Playgroud)

总结一下:

  • 如果 A 类中没有 ctor,则永远不会生成守卫
  • 使用 anaon-ns 也可以防止守卫
  • 使静态成员成为m静态局部变量foo()仍然会生成防护(使用-fno-threadsafe-statics)(注释/取消注释上面示例中的相应行)

那么,如何防止在具有Actor 的案例类中生成守卫并且不可能使用 anon-ns 呢?

wim*_*aan 3

抑制守卫的关键特性是 constinit 和 constexpr ctors:

#include <cstdint>

struct A {
    inline constexpr A(uint8_t v) : m{v} {} // without constexpr it should not compile, but does anymay
    auto m1() const {
        return m;
    }
private:
     uint8_t m{0};
};

template<typename T>
struct X {
    static auto foo() {
        return m.m1();
    }
    constinit inline static T m{2}; // requires constexpr ctor
};
int main() {
    return X<A>::foo();    
}
Run Code Online (Sandbox Code Playgroud)

由于constinit初始化必须在编译时执行,因此不需要生成防护。这需要一个constexpr演员。在上面的示例中,ctor(至少对于 gcc)可以在没有 的情况下声明constexpr,但这可能是一个未决的错误。