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?