Use of macros to aid visual parsing of SFINAE template metaprogramming
Rule #1 of code formatting: Write readable code.

Rule #2: Don't do anything people tell you not to do... until you know better.

The rules against macros are wise because macros can often be very unintuitive.  However, as you have noticed, there are situations where they are very helpful.  The problem with macros is that they appear to be a panacea for formatting, and it is not until  much later that you realize there were serious fundamental issues.

That being said, they're in the language.  They have uses.  So if you take the time to understand them, then you can start to use them wisely.  The two major issues for macros are:


They are global symbols, causing surprise replacements in the most unlikely of places
It is easy to write a macro that looks like it does what you want, when it actually compiles into something else.


Global symbols

Nothing is worse than having someone else's symbols screw with your code.  If someone defines a macro, and it conflicts with your code, the error is almost always unreadable.  Consider the most nefarious one, #define max (a, b) ((a)&gt;(b) ? (a) : (b)), which is defined as part of windows.h.  If you've been writing Linux apps, you'll find this suddenly breaks when you had a local named "max."

By your choice to #undef the symbols at the end, it is clear you are aware of this.  You did a good job of making sure your defines don't hurt someone else.  However, you are still at the whim of anyone who uses the same names as you carelessly.  So good job with being careful, but you're not out of the woods.

** Surprise compilations **

The number on reason why people dislike macros is that they often do things you did not expect.  For example, in the max example, a can get evaluated twice.  Also, macros and commas don't play well.  Macros are generally unaware of brackets, so things like max(getValue(1, 2), getValue(3, 4)) can surprise you with errors.  Your code doesn't have any of these, but always be aware of the costs when you're trying to bend code style rules.

However, you do have a few interesting tidbits.  For example, did you know that you shouldn't say std::enable_if in a macro?  That will do a context-specific search for a namespace named "std."  In the wrong situations, that could cause problems.  The correct phrasing is ::std::enable_if, which forces it to look in the global scope for the right std.

Think of others

So, in you cases, the macros work.  You generally thought it through.  Now lets take this code into a business scenario.  Developers with much less macro practice than you are going to work on this code.  They are going to develop stylistic habits to take parts of how you write.  Do you really get enough readability here to warrant potentially confusing code down the line?

Options

So what else can you do?  Since macro definitions are usually treated as "hard to read," I feel no qualms writing a few struct to help out.  By using structs, I get to avoid the global issues of macros, and they always compile the way you expect them to.

Consider using a template template argument like this:

template &lt;template &lt;typename&gt; Pred, T&gt;
struct subfail_unless
: std::enable_if&lt;Pred&lt;typename std::decay&lt;T&gt;::type&gt; &gt;
{ };

template&lt;typename T,
         typename subfail_unless&lt;std::is_integral, T&gt;::value &gt;
explicit Object( T&amp;&amp; t      ) { init(long  (t)); }

template&lt;typename T,
         typename subfail_unless&lt;std::is_floating_point, T&gt;::value &gt;
explicit Object( T&amp;&amp; t, ... ) { init(double(t)); }


Why I like this:


If you are writing code like this, you MUST know SFINAE, so you aren't going to be threatened by the templating.
It you are are just reading this, you don't need to know why it works, you just need to recognize the words that matter.


Consider how few extra characters this has.

macros:              SUBFAIL_UNLESS(     IS_FLOATING       (T))
templates:  typename subfail_unless&lt;std::is_floating_point, T&gt;::value
---------------------------------------------------------------------
difference: typename                std::                     ::value



This code can now be reused in a header, instead of needing to #define it everywhere you intend to use it.  It is now using only namespaced structs, so it is as safe as any other code.