c++ static member initialization (warning, hardcore :) )

Status
Not open for further replies.

Projectitis

Well-known member
Hi all,

I have these defs:

Code:
enum class GUIIconType {
	none = 0,
	check,
	checkCircle,
	close,
	closeCircle
};

typedef struct {
	uint32_t index;
	int8_t ox;
	int8_t oy;
	BitmapRotation r;
} GUIIconPart;

typedef struct {
	uint8_t len;
	GUIIconPart parts[];
} GUIIconParts;

typedef std::map<GUIIconType,GUIIconParts> GUIIconAllParts;

And in the class I am trying to define a static member of type GUIIconAllParts like this:

Code:
static const GUIIconAllParts iconParts = {
	{ GUIIconType::checkCircle, // GUIIconType
		{ 2,	// GUIIconParts.len
			{	// GUIIconParts.parts
				{ 1, 0, 0, BitmapRotation::none },	// GUIIconPart
				{ 30, 0, 0, BitmapRotation::none }	// GUIIconPart
			}
		}
	}
};

The compile error I get is:

Code:
error: in-class initialization of static data member 'const GUIIconAllParts mac::GUIIcon::iconParts' of incomplete type

error: could not convert '{{checkCircle, {2, {{1, 0, 0, none}, {30, 0, 0, none}}}}}' from '<brace-enclosed initializer list>' to 'const GUIIconAllParts {aka const std::map<mac::GUIIconType, mac::GUIIconParts>}'

Where am I going wrong?
 
There are two issues in your code.

  • You can not initialize non literal static types directly in the a class declaration. You need to do that in some cpp file
  • Your array GUIIconPart parts[] needs a defined length otherwise the compiler can't know how much space to allocate in your map

Here something which compiles:

test.h
Code:
#include "Arduino.h"
#include <map>

enum class GUIIconType {
	none = 0,
	check,
	checkCircle,
	close,
	closeCircle
};

typedef struct {
	uint32_t index;
	int8_t ox;
	int8_t oy;
	//BitmapRotation r; // declaration missing but irrelevant for the example....
} GUIIconPart;

typedef struct {
	uint8_t len;
	GUIIconPart parts[4];  // need to define the length of the array
} GUIIconParts;

typedef std::map<GUIIconType,GUIIconParts> GUIIconAllParts;


class Test
{
    static const GUIIconAllParts iconParts;    
};

Here the corresponding definition of GUIIconAllParts:

test.cpp
Code:
#include "test.h"

const GUIIconAllParts Test::iconParts
{
    {GUIIconType::checkCircle, 
      {2, 
        {
          {1, 0, 0},
          {30,0,0}
        }
      }
    },
    {GUIIconType::check, 
      {3, 
        {
          {4, 5, 6},
          {7, 8,12}
        }
       }
    }
};

Hope that helps
 
Last edited:
BTW: In case you don't know (or don't want to know) the size of your parts array beforehand you might consider changing it to vector<GUIIconPart>. If so, you probably don't need the uint8_t len anymore and you can make everything a bit simpler by directly using the vector of GUIIconParts in the map:

test.h
Code:
#include "Arduino.h"
#include <map>
#include <vector>
#pragma once

enum class GUIIconType {
	none = 0,
	check,
	checkCircle,
	close,
	closeCircle
};

struct GUIIconPart {           // typedef struct is somehow outdated. c++ can handle normal struct declarations
	uint32_t index;
	int8_t ox;
	int8_t oy;
	//BitmapRotation r;
} ;

using GUIIconAllParts = std::map<GUIIconType, std::vector<GUIIconPart>>;  // directly add the vector to the map...

class Test
{
    static const GUIIconAllParts iconParts;
};

test.cpp
Code:
#include "test.h"

const GUIIconAllParts Test::iconParts
{
  {
    GUIIconType::checkCircle, 
    {
      {1, 0, 0},
      {30,0,0}       
    }
  },
  {
    GUIIconType::closeCircle, 
    {
      {4, 5, 6},
      {7, 8,12},
      {4, 5, 6},
      {7, 8,12},
      {4, 5, 6},
      {7, 8,12}
    }
  }   
};
 
Awesome! On both counts. Vector solves my problem here, as long as the overhead of adding the vector library isn’t bigger than assigning fixed length arrays ;) Will check tonight. There will be something like 200 icons in the list, each made up of between 1 and 3 parts.
 
Awesome! On both counts. Vector solves my problem here, as long as the overhead of adding the vector library isn’t bigger than assigning fixed length arrays ;) Will check tonight. There will be something like 200 icons in the list, each made up of between 1 and 3 parts.

So if I pack my data:
  • 200 icons with 2 parts on average each
  • 1 byte overhead for each icon (len)
  • Each part 4 bytes long
I'll end up with around 1.8k of data. this is the minimum I can hope for.
Just adding map and vector to the project add 49k of flash!!
So I'll pack my data and iterate instead of using a map :)
 
He, he, there is no such thing as a free lunch :D On the other hand, NXP won't refund any money for unused flash bytes... :))
 
Haha! That is true. But I hate seeing that counter increase :) it's over 10% now - arrrgh :D
I enjoy a challenge anyway.
 
Status
Not open for further replies.
Back
Top