Adding helpful requires macros to the enable_if utility
These following set of macros, I have found very useful in C++:
#define BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE(...) __VA_ARGS__>::type
#define BOOST_FUNCTION_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE
#define BOOST_CLASS_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__)>::type
#define BOOST_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), int>::type = 0
Which I use like the following
For functions:
template <class T>
BOOST_FUNCTION_REQUIRES(boost::is_arithmetic<T>::value)
(T) foo(T t) { return t; }
And C++11 functions:
template
On Friday 27 June 2014 09:10:33 paul Fultz wrote:
These following set of macros, I have found very useful in C++:
#define BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE(...) __VA_ARGS__>::type #define BOOST_FUNCTION_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE
#define BOOST_CLASS_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__)>::type
#define BOOST_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), int>::type = 0
Which I use like the following
For functions:
template <class T> BOOST_FUNCTION_REQUIRES(boost::is_arithmetic<T>::value) (T) foo(T t) { return t; }
And C++11 functions:
template
T foo(T t) { return t; } Class specializations:
template
class A { ... }; template <class T> class A
{ ... }; template <class T> class A
{ ... }; It would be nice if these were the added with the enable_if utility with boost.
Frankly, I'd prefer using enable_if directly instead of macros.
On Fri, 27 Jun 2014 09:35:14 -0700, Andrey Semashev
On Friday 27 June 2014 09:10:33 paul Fultz wrote:
These following set of macros, I have found very useful in C++:
#define BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE(...) __VA_ARGS__>::type #define BOOST_FUNCTION_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), BOOST_ERROR_PARENTHESIS_MUST_BE_PLACED_AROUND_THE_RETURN_TYPE
#define BOOST_CLASS_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__)>::type
#define BOOST_REQUIRES(...) typename boost::enable_if_c<(__VA_ARGS__), int>::type = 0
Which I use like the following
For functions:
template <class T> BOOST_FUNCTION_REQUIRES(boost::is_arithmetic<T>::value) (T) foo(T t) { return t; }
And C++11 functions:
template
T foo(T t) { return t; } Class specializations:
template
class A { ... }; template <class T> class A
{ ... }; template <class T> class A
{ ... }; It would be nice if these were the added with the enable_if utility with boost.
Frankly, I'd prefer using enable_if directly instead of macros.
-1. I find the use of macros to be far more readable than the direct use of templates. In fact, I was earlier toying with the idea of writing such macros myself. Needless to say that I would find them to be very helpful. Paul, can the concept be extended to a DSEL-like utility? Something along the lines of: template <class T> BOOST_FUNCTION_REQUIRES(is_foo(T) and is_bar(T)) (T) foo(T t) { return t; } where "is_foo", "and", and "is_bar" are PPMP keywords. "Non-standard" conditions can be introduced via the "explicit" keyword, like: template <class T> BOOST_FUNCTION_REQUIRES(is_foo(T) and is_bar(T) or explicit(is_baz<T>::value)) (T) foo(T t) { return t; } , or clients can be given a mechanism to hook in their own keywords. (I have a mental sketch of how the latter could work, nothing implemented or tested.) Just thinking out loud ...
I find the use of macros to be far more readable than the direct use of templates. In fact, I was earlier toying with the idea of writing such macros myself. Needless to say that I would find them to be very helpful.
Besides readability, they actually help avoid the most vexing parse in C++(something template aliases can't fix).
Paul, can the concept be extended to a DSEL-like utility?
Well you can already write something like this on compilers that support
`constexpr`:
template <class T>
BOOST_FUNCTION_REQUIRES(is_foo<T>() and is_bar<T>())
(T) foo(T t) { return t; }
This could be made to work on older compilers by using expression templates,
but
then using literals such as `is_foo<T>::value` would fail. Perhaps a second
macro like `BOOST_FUNCTION_REQUIRES_E` could be written to help avoid the
confusion. Plus, having separate `_E` macros can actually still be useful in
C++11 because of limitations of `constexpr`. For example, say we use a
`trait`
function that deduces the type parameters from a variable:
template class Trait, class... Ts>
constexpr auto trait(Ts&&... xs)
{
return Trait(std::forward<Ts>(xs)...);
}
template <class T>
T foo(T t, BOOST_REQUIRES_E(trait
participants (4)
-
Andrey Semashev
-
Mostafa
-
paul Fultz
-
pfultz2