I have an error reporting system where unconfigured errors are ignored (configuration only means that there is a typedef for this error). Therefore, in those places where something is reported, it should become NOP if there is no typedef.
The problem is that I want to generate the SFINAE expression locally in order to be able to write something like (this is a work in progress, please ignore the naming, etc.):
Oh. And sorry. It must be compatible with C ++ 03/98. Stupid built-in compilers ...
template<uint32_t ID>
struct Error { enum { value = ID }; };
enum { IGNORE_UNKNOWN = 1, DISALLOW_UNKNOWN = 2 };
namespace config {
struct TheConfig {
typedef Error<1> Error1;
typedef Error<2> Error2;
enum { MISSING_ERROR_POLICY = IGNORE_UNKNOWN };
};
}
template<typename T>
struct ReportEvent {
inline void operator()() {
T event;
std::cout << "Called with error event" << event.value << std::endl;
}
};
struct IgnoreEvent {
inline void operator()() {
std::cout << "Event ignored" << std::endl;
}
};
#define REPORT_ERROR(event_name) \
....
int f() {
REPORT_ERROR(Error1);
REPORT_ERROR(Error5);
}
My current implementation, unfortunately, gives me (in visual studio) C2951: "type declarations are allowed only in the global namespace, or in the class." But going to the sub dummy class gives C2892: "The local class should not have member templates."
#define REPORT_ERROR(event_name) \
{ \
template<typename T> struct void_type { \
typedef void type; \
enum { exists = false }; \
}; \
template<typename T, typename = void> \
struct type_if_exists_##event_name : void_type<void> {}; \
template<typename T> \
struct type_if_exists_##event_name<T, typename void_type<typename T::event_name>::type> \
{ \
typedef typename T::event_name type; \
enum { exists = true }; \
}; \
static_assert(config::TheConfig::MISSING_ERROR_POLICY == IGNORE_UNKNOWN || \
type_if_exists_##event_name<config::TheConfig>::exists, \
"COM event " #event_name " can be reportet, but is not configured."); \
std::conditional<type_if_exists_##event_name<config::TheConfig>::exists, \
ReportEvent<type_if_exists_##event_name<config::TheConfig>::type>, \
IgnoreEvent>::type()() \
}
- SFINAE ?