0

I have BOOST installed on my Windows PC with Mingw. The BOOST installation basically works, but when I use a macro I got following error message:

macro "BOOST_PP_NOT_EQUAL_1" defined here

Under Linux it works!

Anybody out there what can help me? Or at least give some hint.

Here are my marco's:

#include <iostream>
#include <ostream>
#include <set>

#include <boost/preprocessor.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

class EnumShowValue {
private:
    static bool showValueFlag;
public:
    explicit EnumShowValue(const bool flag) { EnumShowValue::showValueFlag  = flag; }

    static bool showValue() { return EnumShowValue::showValueFlag; }
};

inline std::ostream &operator <<(std::ostream &os, const EnumShowValue &) { return os; }

// Defines a entry of the enumerations either with an initialization value or with a default value.
#define ENUM_FIELD(C, T, ARGS)\
    BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE(ARGS), 2),\
                    BOOST_PP_TUPLE_ELEM(0, ARGS) = BOOST_PP_TUPLE_ELEM(1, ARGS),\
                    BOOST_PP_TUPLE_ELEM(0, ARGS)),

// Define output of a single enumeration value.
#define ENUM_OUTPUT_CASE(C, T, ARGS)\
    case T::BOOST_PP_TUPLE_ELEM(0, ARGS):\
        os << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(0, ARGS));\
        break;

#define ENUM_INSERT(C, T, ARGS)\
    this->insert(T::BOOST_PP_TUPLE_ELEM(0, ARGS));

#define ENUM_DEFINE_SET(C, T, ARGS)\
    class Collection : public std::set<C> {\
    public:\
        Collection() : std::set<C>() {\
            BOOST_PP_SEQ_FOR_EACH(ENUM_INSERT, C, ARGS)\
        }\
    };\
    Collection  collection;

// Works only if the enumeration values are unique.
#define ENUM(C, T, ARGS) \
enum class C : T {\
BOOST_PP_SEQ_FOR_EACH(ENUM_FIELD, C, ARGS)\
};\
ENUM_DEFINE_SET(C, T, ARGS)\
std::ostream &operator <<(std::ostream &os, const C val);\
std::ostream &operator <<(std::ostream &os, const C val) {\
    switch (val) {\
    BOOST_PP_SEQ_FOR_EACH(ENUM_OUTPUT_CASE, C, ARGS)\
    default:\
        os << "illegal value: " << BOOST_PP_STRINGIZE(C);\
        if (!EnumShowValue::showValue()) {\
            os << '(';\
            if (sizeof(T) == 1) {\
                os << static_cast<int>(val);\
            } else {\
                os << static_cast<T>(val);\
            }\
            os << ')';\
        }\
    }\
    if (EnumShowValue::showValue()) {\
                    os << '(';\
                    if (sizeof(T) == 1) {\
                        os << static_cast<int>(val);\
                    } else {\
                        os << static_cast<T>(val);\
                    }\
                    os << ')';\
    }\
    return os;\
}

and a example how to use: (it defines some logging levels)

namespace logging {
    ENUM(Level, unsigned char, ((DEBUG)(INFO)(WARNING)(ERR)))
}
Rainer
  • 51
  • 5
  • There are multiple things wrong here; I could write articles on this. I could also in principle help you debug it and show techniques, but not as a single one-off answer to a single generic question. What are your specs? Are you simply after the ENUM macro, or all of them? Can you flex on how you're building the macro (maybe, giving up boost pp as the core approach and using X-macros is the thing to recommend?) – H Walters Aug 18 '21 at 00:29
  • Sorry for the long break. I was reading about x-macros. Finally I came to the conclusion that a solution based on x-macros would be ok. But I need help to do this. Can you help me? – Rainer Aug 26 '21 at 18:18
  • "Sorry for the long break" ...no worries. Try looking at a few other examples, such as [here](https://stackoverflow.com/questions/6635851/real-world-use-of-x-macros). – H Walters Aug 26 '21 at 22:29

1 Answers1

0

If found a solution show below.

What I was not able so solve is a more general solution in with I can define the name of the enumeration, the basic type and the values in a #define or in an template.

Has anybody an idea how to do this?

#include <cstdint>
#include <iostream>
#include <ostream>

#define Days\
    X(Monday, = 100)\
    X(Tuesday,)\
    X(Wednesday,)\
    X(Thursday,)\
    X(Friday,)\
    X(Saturday, = 110)\
    X(Sunday,)

enum class Weekdays : uint8_t {
    #define X(a, b) a b,
    Days
    #undef X
};

std::ostream &operator <<(std::ostream &os, const Weekdays e);

std::ostream &operator <<(std::ostream &os, const Weekdays e) {

    switch (e) {
        #define X(a, b) case Weekdays::a: os << #a; break;
        Days;
        #undef X
        default:
            os << "invalid value: Weekdays=" << uint64_t(e);
    }

    return os;
}

int main(const int /*argc*/, const char *const /*argv*/[]) {

    std::cout << Weekdays::Monday << std::endl;
    std::cout << Weekdays::Tuesday << std::endl;
    std::cout << Weekdays::Saturday << std::endl;
    std::cout << Weekdays(99) << std::endl;

    return EXIT_SUCCESS;
}
Rainer
  • 51
  • 5