Reputation: 1234
I'm still unsure of whether it is a good idea to ask this, as it's somehow a "coding style" problem (and those are inherently subjective), but I hope it will be objective enough turned that way.
If it turns out it isn't, I apologize for asking it here.
I'd like to ask two questions:
What I don't ask however is whether you personally like this code or not. I can't prevent you from saying so if you want, and I won't mind if you do, but I'd like to have a reason why it's either good or bad and it may help leading this question to the dark side of potentially opinion-based questions (assuming it isn't already, again, I apologize if it is).
Recently, I wanted to write some traits many of them being extremely simple. However, each of those required some kind of repetitive metaprogramming code. I ended up using a macro to make the code more compact and less repetitive with a code like this:
#include <type_traits>
//...
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = void_type<T...>::type;
#define UNARY_EXPRESSION_TYPE_TRAIT(trait_name, expression, expression_type, \
type_name) \
namespace detail_generated { \
template<class type_name, class = void> \
struct trait_name : std::false_type {}; \
\
template<class type_name> \
struct trait_name<type_name, void_t<decltype(expression)>> : \
std::integral_constant< \
bool, std::is_same<decltype(expression), expression_type>::value \
> {}; \
} \
template<class type_name> \
struct trait_name<type_name> : detail_generated::trait_name<type_name> {};
UNARY_EXPRESSION_TYPE_TRAIT(is_preincrementable,
++std::declval<Incrementable&>(),
Incrementable&, Incrementable)
UNARY_EXPRESSION_TYPE_TRAIT(is_predecrementable,
--std::declval<Decrementable&>(),
Decrementable&, Decrementable)
UNARY_EXPRESSION_TYPE_TRAIT(is_contextually_convertible_to_bool,
!std::declval<T>(), bool, T)
#undef UNARY_EXPRESSION_TYPE_TRAIT
// ...
In this specific case it avoids repetition of "boilerplate metaprogramming constructions" and I don't see that many drawbacks (most of them being mitigated by the immediate use of the macro, and its immediate undefinition).
However, I'm usually not really comfortable around macros (I find them obfuscated, and usually replaceable) and I know they are usually regarded as bad or "evil". Unfortunately I couldn't find either a way to replace it, a reason to keep it, or a reason to avoid it, even after reading the following questions:
(and that one because it's fun although not really useful:)
I am not satisfied with their answers because they either:
I can't objectively judge my code, and I can't find any good replacement for that macro (except actually doing the preprocessor's job and copy-pasting that macro wherever I need which strikes me as at least equally bad). Maybe I just don't see the obvious and fatal disadvantages of that macro, or maybe I even didn't fully understand why using macros is discouraged.
Edit: removed the leading underscore in some names as recommended in the comments (such names are reserved)
Upvotes: 2
Views: 154
Reputation: 28987
The problem with macros is that they disregard the nice structuring constructs we have in C++. OTOH, this strikes me as a good use of macros:
I would say "go for it".
Upvotes: 1