Macro compiles with GCC but not with VS11

c++, c++11, gcc, macros, visual-studio-2012

Solution

template<typename T> struct is_io_type : std::false_type {};
template<> struct is_io_type<int> : std::true_type {};
template<> struct is_io_type<double> : std::true_type {};
template<> struct is_io_type<std::string> : std::true_type {};

Then, instead of your macro, simply type:

static_assert( is_io_type<T>::value, "Type not defined for this template." )

which is about as verbose and not nearly as obscure or hard to figure out what the heck is going on.

Now, suppose we really need the `is_base_of` functionality.

template<typename T,typename=void> struct is_io_type : std::false_type {};
template<> struct is_io_type<int,void> : std::true_type {};
template<typename T> struct is_io_type<T,typename std::enable_if<std::is_base_of<int, T>::type> : std::true_type {};
template<> struct is_io_type<double,void> : std::true_type {};
template<typename T> struct is_io_type<T,typename std::enable_if<std::is_base_of<double, T>::type> : std::true_type {};
template<> struct is_io_type<std::string,void> : std::true_type {};
template<typename T> struct is_io_type<T,typename std::enable_if<std::is_base_of<std::string, T>::type> : std::true_type {};

which gets pretty verbose.

But rather than creating a variardic macro expansion at the point where we use the macro, we can instead use a macro to build the above type trait specializations.

So you first create your type trait, then extend it:

CREATE_TYPE_CATEGORY( is_io_type );
ADD_BASE_TYPE_CATEGORY( is_io_type, int );
ADD_BASE_TYPE_CATEGORY( is_io_type, double );
ADD_BASE_TYPE_CATEGORY( is_io_type, std::string );

which would write the code above a bit less verbosely. It also supports distributed trait modification: if someone creates a new type that should be `is_io_type`, they can use the above macro after introducing the type and it (and its descendents) become an io type.

Problem

I have written the following code to assist restricting my template functions to certain types, with meaningful error message when other types were used. I had the idea from a different question in stackoverflow, on which I still can't comment because I am new here. The macro compiles flawlessly under linux GCC but not with Visual Studio 2012. ``` #include <string> #include <iostream> #include <vector> #include <cassert> #include <type_traits> #define ISALLOWED(DerivedT) (std::is_same<T, DerivedT>::value)||(std::is_base_of<T,DerivedT>::value) #define FE_1(WHAT, X) WHAT(X) #define FE_2(WHAT, X, ...) WHAT(X) || FE_1(WHAT, __VA_ARGS__) #define FE_3(WHAT, X, ...) WHAT(X) || FE_2(WHAT, __VA_ARGS__) #define FE_4(WHAT, X, ...) WHAT(X) || FE_3(WHAT, __VA_ARGS__) #define FE_5(WHAT, X, ...) WHAT(X) || FE_4(WHAT, __VA_ARGS__) #define FE_6(WHAT, X, ...) WHAT(X) || FE_5(WHAT, __VA_ARGS__) //... repeat as needed #define GET_MACRO(_1,_2,_3,_4,_5,_6,NAME,...) NAME #define FOR_EACH(action,...) \ GET_MACRO(__VA_ARGS__,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1)(action,__VA_ARGS__) // this is where you need to add types #define ASSERTIOTYPES \ static_assert(FOR_EACH(ISALLOWED,\ int,double,std::string\ ),"Type not defined for this template."); template<class T> std::ostream & operator<<(std::ostream &os, const std::vector<T> & v) { ASSERTIOTYPES; os << "["; for (size_t i = 0; i < v.size(); i++) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]"; return os; } ``` The error message is: error C2977: 'std::is_same' : too many template arguments And it appears only when I define ASSERTIOTYPES with more than one type, but when it is defined with only one type, for example: ``` #define ASSERTIOTYPES \ static_assert(FOR_EACH(ISALLOWED,\ int\ ),"Type not defined for this template."); ``` ... the code compiles normally. Any idea how to solve this?

Original source

Related problems