0

I have a struct with a static field I want to deprecate. However, for now I still want to initialize it. The following snippet produces a warning under MSVC and GCC (but not Clang):

struct A {
    ~A();
};

struct B {
    [[deprecated]] static A X;
};

A B::X; //warning C4996: 'B::X': was declared deprecated

Interestingly, if I remove ~A();, the warning disappears.

Is there way to initialize B::X without producing a warning, without resorting to hacky pragmas or such?

Wouter
  • 538
  • 6
  • 15

1 Answers1

1

The warning disappears when you remove the destructor because then A can be trivially destructed (and also constructed), meaning that the compiler doesn't need to emit actual code to initialize anything, and thus does not generate code that references B::X. Therefore, there is no trigger to emit the warning.

This also hints at a possible workaround: Make B::X something "trivial", e.g. a reference. For example (live on godbolt):

struct A {
    ~A();
};

struct B {
  static A helper;
  [[deprecated]] static A & X;
};

A B::helper;
A & B::X = B::helper;

This does not produce the warning, only where it is actually used. And in most cases, this workaround should not change the semantics of your program.

As a side note, the static members are initialized in the order of their definition, see e.g. this answer.

Sedenion
  • 5,421
  • 2
  • 14
  • 42
  • The workaround does work well, thank you! I'm still not sure about the cause of this problem, because e.g. replacing the destructor with a constructor does not produce a warning. – Wouter Nov 24 '22 at 09:51
  • 1
    Looking at the gcc assembly on godbolt, my guess would be that the construction itself is not triggering the warning. However, for destruction of a class with a non-trivial destructor, `__cxa_atexit()` is called during initialization and a reference to the static member `A` is passed. This ensures that the object is properly destructed at the end of the program. My guess is that this access is triggering the warning. I.e. calling a constructor is a common thing for every variable (and thus the devs of the compilers ensured no warning there), destruction of a static variable is rather special. – Sedenion Nov 24 '22 at 18:55