1

I have a class that contains a static member which is set to the class itself evaluated in a specific way. This is an example

struct A{
    constexpr A(const int i):_i(i){}

    int _i;
    static const A One;
};

constexpr A A::One=A(1);

This code compiles and runs with gcc and clang, but if I compile with the Intel compiler icc (v19.0.4.227) (or on Godbolt with ICC19.0.1) I get

icc -std=c++17 test.cpp
test.cpp(10): error: member "A::One" (declared at line 7) was previously not declared constexpr
  constexpr A A::One=A(1);

Note that I cannot initialize A::One in the struct A{} definition since the type would be incomplete.

Is there a workaround that would work with the Intel compiler?


A main that uses this would look like, if you wanted to actually run this instead of just compile.

int main()
{
  std::cout << A::One._i << std::endl;
  return 0;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
user3646557
  • 299
  • 2
  • 9
  • 1
    Why are you using `constexpr A A::One=A(1);` instead of `const A A::One=A(1);`? – NathanOliver May 14 '20 at 21:40
  • For some reason GCC10 and clang10 do accept this code: https://godbolt.org/z/LdAFWt no warnings even with `-Wall -Wextra`. So does MSVC. But yes, ICC on godbolt reproduces this https://godbolt.org/z/CgYEFo – Peter Cordes May 14 '20 at 21:57
  • 2
    This appears to be [valid](https://stackoverflow.com/questions/11928089/static-constexpr-member-of-same-type-as-class-being-defined). Probably icc bug. – cigien May 14 '20 at 22:09
  • Your `main()` example would better use it in a template argument list, or a switch case, or somewhere that a constexpr is required. This would completely negate NathanOliver's comment to just use `const` instead. – Ben Voigt May 14 '20 at 22:21
  • First of all, this is of course just the simplest code that triggers the exception. But to come to @NathanOliver's comment, we use constexpr because this is compiled to a shared library, and we discovered that if we declared it const (as opposed to constexpr), there are instances were A::One._i is equal to 0 as opposed to one. Setting the definition as constexpr solves the problem. – user3646557 May 14 '20 at 23:39
  • When you're seeing it as zero, that might be due to code not seeing the `const A A::One=A(1);` definition. Without that, gcc for example will emit static-initializer code to copy from actual static storage for something like `int foo = A::One._i;` https://godbolt.org/z/6RXQ9i – Peter Cordes May 15 '20 at 00:01

0 Answers0