0

Having 2 strange warnings during auto generation enum + string items...

EnumItems.h (2 times included header to build enum and string array + possibility to have multiple enums and single boilerplate)

#ifdef ENUM_ONCE_INCLUDED
    #undef ENUM_NUMBERED
    #undef ENUM_ITEM
    #define ENUM_NUMBERED(i, n) *(new TemporaryItem( #i, n ))
    #define ENUM_ITEM(i) *(new TemporaryItem( #i ))
  #undef ENUM_ONCE_INCLUDED
#else
    #define ENUM_NUMBERED(i, n) i = n
    #define ENUM_ITEM(i) i
  #define ENUM_ONCE_INCLUDED
#endif // ENUM_ONCE_INCLUDED
#ifndef ENUM_ITEMS
#error Undefined ENUM_ITEMS # !
#elif ENUM_ITEMS == 1
{
    ENUM_NUMBERED(E_LOREM, 0),
    ENUM_NUMBERED(E_IPSUM, 1),
    ENUM_ITEM(E_DOLOR),
    ENUM_NUMBERED(E_SIT, 20)
}
#endif // ENUM_ITEMS
#ifdef ENUM_ONCE_INCLUDED
    ;
    #if defined(__ICCARM__) && defined(DEBUG)
        #pragma diag_suppress=Pa105
    #endif
#else
    ,_once = TemporaryItem::PostProcess(states, sizeof(states));static_cast<void>(_once);
    #if defined(__ICCARM__) && defined(DEBUG)
        #pragma diag_default=Pa105
    #endif
#endif // ENUM_ONCE_INCLUDED

*.cpp(s)

#define ENUM_ITEMS 1
namespace
{
    enum second_t
    #include "EnumItems.h" // standard enum items - 1st include
    // F12 jumps to particular item in header
}
static const char *states[21] =
#include "EnumItems.h" // struct TemporaryItem* - 2nd include

Sigle expected a declaration with additional brackets in EnumItems.h (for multiple enums)
- or lot of this declaration has no storage without in Visual Studio Error List only
and Remark[Pa105]: this directive is inside an active namespace scope ## in IAR, but this is true in most cases unfortunately.

Is it possible to remove them somehow (except supress in IAR) ?

Or is there any similar and better way how to write enum + string counterparts without need to compare and synchronize their separate instances again and again ?

Mind final target is old-fashioned IAR EC++ compiler.

It is also unlikely impossible to use names for ENUM_ITEMS definitions without hard to read breakneck tricks.

Polymorphic struct/class used to check & store preprocessor generated definitions and rewrite them by string arrays.

struct TemporaryItem {
    const char *name; int pos;
    TemporaryItem(const char *n) { name = n; pos = INT_MIN; /* auto-generated */ }
    TemporaryItem(const char *n, int p) { name = n; pos = p; }
    static char PostProcess(const char **process, size_t size) {
        size /= sizeof(char *); // array size
        TemporaryItem **source = new TemporaryItem*[size];
        memcpy(source, process, sizeof(TemporaryItem*) * size); // copy definitions
        memset(process, 0, sizeof(TemporaryItem *) * size); // reset final range
        int stLogicNumber = source[0]->pos;
        if (stLogicNumber == INT_MIN) stLogicNumber = 0; // no logic shift
        int finalPos = 0; // default item destination
        for (size_t i = 0; i < size; i++) {
            TemporaryItem *current = source[i];
            if (current == NULL) break; // no more defined
            int defPos = current->pos;
            if (defPos == INT_MIN) defPos = finalPos; // auto-generated
            else if (stLogicNumber < 0)
                    defPos -= stLogicNumber; // move forward by 1st logic value

            if (defPos >= finalPos && static_cast<unsigned>(defPos) < size)
                finalPos = defPos; // set valid destination
            else __debugbreak(); // block backward && out of bounds
            process[finalPos] = current->name;
            delete current; // remove processed definition
            finalPos++;
        }
        delete[] source; // remove temp array
        return 0;
    }
    operator const char *() // collect TemporaryItem-s definitions in destination array
    { return reinterpret_cast<const char *>(this); }
};

1st version having nice get/set operators also here easily map c++ enums to strings, but enum items are useless mixed by preprocessor to single line there.

Jan
  • 2,178
  • 3
  • 14
  • 26
  • 5
    Maybe just my opinion but I don't see how this allows for "easily maintainable enums" – Kevin Dec 22 '21 at 22:02
  • Title and first sentence are definitely at odds with each other. – sweenish Dec 22 '21 at 22:02
  • Sorry not native... It was very hard to keep both synchronized in huge project - very often someone changed enum, but not strings description/array, if you decrease value, you may get some repeated without any word from compiler... – Jan Dec 22 '21 at 22:08
  • 2
    Your code is really complicated... writing statefull header files is just going to bite you. Really, just using two separate headers would be _significantly_ simpler... I'm sure there are _endless_ C++ libraries for creating stringify-able enums. Does https://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string answer your question? https://stackoverflow.com/questions/9907160/how-to-convert-enum-names-to-string-in-c TBH, doing it manually is simple, great and saves you from spending more time fixing unreadable code. Is there sense in fixing such code at all? – KamilCuk Dec 22 '21 at 22:19
  • 2
    `Getting lot of these` Please post the _exact full all verbatim_ error messages you are getting. Please do not post "something like". Please kindly create an [MCVE] - exact files you are getting error from, so that error line numbers properly align with the source code. To which line number do errors refer to? Why are you defining `states[12]` the same variable twice, or is this code block representing two separate source files? If the latter - why would you want to put enum definitions in one centralized point (the header `EnumItems.h`) for all source files in your project? – KamilCuk Dec 22 '21 at 22:23
  • The `typedef enum ST_ENUM { };` seems like a candidate for "no storage class or type specifier ". A typedef without a name? – BoP Dec 22 '21 at 22:33
  • I am using this with debug only https://stackoverflow.com/questions/65366996/getter-setter-in-c-c-project and there was a lot of operator template methods in single file anyway... Warnings are exact copy/paste and even marked here ?? It is reproducible (except missed namespaces around include). Was forced to declare fixed size and there are also unused values between items. Single file Is just a helper you can remove in some builds and reduce changes in too much files (git). – Jan Dec 22 '21 at 22:43
  • https://stackoverflow.com/questions/28828957/enum-to-string-in-modern-c11-c14-c17-and-future-c20 – n. m. could be an AI Dec 22 '21 at 22:59
  • It's unclear to me that your macros actually help you write easily maintainable enums. I generally advise against using macros if at all possible in C++ because there are numerous down sides that often exceed the benefits - but (if you have your heart set on macros) you might want to look up a technique known as "X macros". X macros offer one way to maintain parallel lists at compile time (e.g. associate a map between a set of enums and a set of something else). It seems such a technique might be useful for you. Personally, I avoid such techniques, but some folks swear by them. – Peter Dec 23 '21 at 00:57
  • When I had to deal with this problem, I wrote a little program (in C++, but Python or whatever would work just as well) to parse the enum's tokens out of the .h file and write out a corresponding .cpp file containing the array of the corresponding strings. With that written, it was just a matter of adding a dependency to my Makefile so that whenever the .h file was touched, `make` would run the program and regenerate the .cpp file. I haven't had any problems keeping things in sync since then, since it happens automatically whenever I compile my app. – Jeremy Friesner Dec 23 '21 at 04:13
  • Separate build step is also option - already using JS to pipe and filter IAR warnings for VS to work with like if they are native, but when it come to multiplatform target and bulid envs & https://en.m.wikipedia.org/wiki/Embedded_C%2B%2B I not care what is under the hood. Point Is put enum items somewhere else and end get rid of never ending compare changed enum vs strings, out of bounds crashes, etc. It works nice even in terrible old/uncompatible compiler, but show few more strange warnings probably intellisense suppose each file is valid C++ source(?) – Jan Dec 23 '21 at 06:11

0 Answers0