I have a macro that is building a class for me. I want to provide a constructor which takes an int if the class itself does not have an int specified as its type. The macro looks something like:
CLASS_DECLARE(NAME, TYPE)\
class NAME { \
public: NAME(const TYPE& x) : value(x) {}\
private: TYPE value; };
I can come close using the boost preprocessor to manually turn this constructor on and off...
CLASS_DECLARE(NAME, TYPE)\
class NAME { \
public: NAME(const TYPE& x) : value(x) {}\
BOOST_PP_EXPR_IF(0, NAME(const int& x) : value(static_cast<TYPE>(x)) {})\
private: TYPE value; };
However, I cannot replace the 0 in the macro with a conditional. I want something like:
CLASS_DECLARE(NAME, TYPE)\
class NAME { \
public: NAME(const TYPE& x) : value(x) {}\
BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(TYPE, int), NAME(const int& x) : value(static_cast<TYPE>(x)) {})\
private: TYPE value; };
However, that expands to something less than helpful:
BOOST_PP_EXPR_IIF_BOOST_PP_BOOL_BOOST_PP_NOT_EQUAL_CHECK_BOOST_PP_NOT_EQUAL_int(0,
BOOST_PP_NOT_EQUAL_int)(MyType(const int& x) : value(static_cast<int>(x)){};
Looking around, it doesn't seem as though BOOST_PP_NOT_EQUAL is intended for this type of comparison. (I am aware of macro expansion issues and have build some "IMPL" macros to try to get things expanded out further. I don't think that is the problem here, however.) Thoughts?
In case anyone else has an issue where they would like this type of specialization, I wanted to post an answer. This solution will work if you have a finite set of types/strings you want to compare and know them at compile time. Here is the example that supports int and uint8_t. The special constructor will only be written for the non-int type.
#include <boost/preprocessor.hpp>
#define TYPE_IS_int 0
#define TYPE_IS_uint8_t 1
#define CLASS_DECLARE(NAME, TYPE)\
class NAME {\
public: NAME(const TYPE& x) : value(x) {}\
BOOST_PP_EXPR_IF(BOOST_PP_CAT(TYPE_IS_, BOOST_PP_EXPAND(TYPE)), NAME(const int& x) : value(static_cast<TYPE>(x)) {})\
private: TYPE value; };
CLASS_DECLARE(MyIntType, int);
CLASS_DECLARE(MyUint8Type, uint8_t);
The macro expands to:
class MyIntType
{
public:
MyIntType(const int& x) : value(x) {}
private:
int value;
};
class MyUint8Type
{
public:
MyUint8Type(const uint8_t& x) : value(x) {}
MyUint8Type(const int& x) : value(static_cast<uint8_t>(x)) {}
private:
uint8_t value;
};