Home > OS >  C Struct/Class Question - How to create static instances of a struct/class
C Struct/Class Question - How to create static instances of a struct/class

Time:11-15

One of those basic C question, my bad.

I'm wondering about you format structs in C such that, in this case, I could get math::Vector2::zero to return a Vector2 where both values are 0.f.

namespace math
{
    struct Vector2
    {
        Vector2() { x = 0.f; y = 0.f; }
        Vector2(float x_, float y_) { x = x_; y = y_; }

        float x, y;

        static math::Vector2 zero = math::Vector2(0.f, 0.f);  // Error is here
    };
};

The error is: error C2027: use of undefined type 'math::Vector2' and: a member with an in-class initializer must be const

Thanks.

CodePudding user response:

While inside the class definition, it doesn't know the complete type (yet) so you can't define a class in terms of itself like that. You must split them apart. For example, if you merely declare the static variable in the class, you can define it elsewhere, but you must be sure that there is only one definition of the variable! That means it should not be in the header, unless it's marked inline (requires c 17).

// header
namespace math {
    struct Vector2 {
        Vector2() { x = 0.f; y = 0.f; }
        Vector2(float x_, float y_) { x = x_; y = y_; }
        float x, y;

        static Vector2 zero; // declare
    };

    // definition is outside class.  Notice, to be in header, _must_
    // be inline.  If you're using older c  , put this in a cpp file
    // and remove inline, and link it in. 
    inline Vector2 Vector2::zero = math::Vector2(0.f, 0.f);
}

CodePudding user response:

There are essentially two ways to create static variables:

  1. struct A
    {
        inline static MyType MyVar = ...; // If `constexpr` is used, `inline` becomes unnecessary.
    };
    
  2. struct A
    {
        static MyType MyVar;
    };
    
    // Must either be in the `.cpp` file, or be `inline`:
    MyType A::MyVar = ...;
    

There are some other options for const variables, but they're rarely used.

The error a member with an in-class initializer must be const means that you provided an initializer inside of the class (option 1), but forgot inline.

However, use of undefined type 'math::Vector2' means that Vector2 is not defined until the end of the class defintion is reached, so option (1) can't be used at all here. Option (2) would work.

CodePudding user response:

The message tells you there are 2 distinct errors:

  1. use of undefined type math::Vector2
  2. A member with an in-class initializer must be const.

Fixes:

for 1.: Move definition (assignment) of zero AFTER the declaration of Vector2 is complete. By the way... You MUST define the static variable in a .cpp file, or in the .h file, adding the keyword inline. The value is assigned

for 2.: Make sure you indicate that zero is a constant. Which is fortunately what you want...

This gives:

namespace math
{
    struct Vector2
    {
        Vector2() { x = 0.f; y = 0.f; }
        Vector2(float x_, float y_) { x = x_; y = y_; }

        float x, y;

        static const Vector2 zero;        // declaration
    };

    inline const Vector2 Vector2::zero{}; // definition
}

Have you considered using this simpler (to read) notation instead ?

namespace math
{
    struct Vector2
    {
        Vector2() = default;
        Vector2(float x, float y) : x(x), y(y) {}

        float x = 0;
        float y = 0;

        static const Vector2 zero;        // declaration
    };

    inline const Vector2 Vector2::zero{}; // definition
}

constexpr'dness is quite obvious in this case? And here is one correct way to declare/define using constexpr.

namespace math
{
    struct Vector2
    {
        constexpr Vector2() = default;
        constexpr Vector2(float x, float y) : x(x), y(y) {}

        float x = 0;
        float y = 0;

        static const Vector2 zero;        // declaration, still cannot define
                                          // as constexpr, because Vector2
                                          // is not yet fully declared.
    };

    inline constexpr const Vector2 Vector2::zero; // definition
}
  •  Tags:  
  • c
  • Related