
On Thu, Jan 22, 2015 at 3:49 PM, Edward Diener
On 1/22/2015 6:05 PM, Matt Calabrese wrote:
On Wed, Jan 21, 2015 at 4:52 PM, Matt Calabrese
wrote: I've found it useful, especially in tests, to easily be able to do
expression validity checking via SFINAE in a static assert.
Bump, and also a couple of additional macros for checking constexpr-ness of an expression are linked farther down in this email, using similar tricks as the SFINAE checks int the previous email (pushing more complicated checks into the body of a lambda such that the macro expands to an expression).
Motivation for this is that often when writing templated code it is difficult to be certain that a specific instantiation is actually constexpr even if the constexpr keyword is used with the function template. For instance, for a matrix type whose value type is a template parameter T, it can be difficult to know if matrix<T>'s multiplication operation actually results in a constexpr object, even if it has constexpr inputs. Particularly when designing such a library, it is useful to be able to write simple tests that check the constexpr-ness of a specified expression in the form of a static_assert. A proof-of-concept implementation of this is linked below:
As an example of such a usage:
////////////////////
int foo(int) { return 0; }
STATIC_ASSERT_CONSTEXPR ( (constexpr int) var = 5, foo(var) );
////////////////////
Produces the error:
prog.cpp:70:1: error: static assertion failed:
********************
Given: constexpr int var = 5;
The following expression was expected to be constexpr but was not: foo(var)
********************
This looks interesting but I am confused about where this implementation is. Is it available somewhere ? is it documented at all ? Are there examples/tests ? Is there a good general of when some of these macros should/would be used in template code ?
Slimmed-down implementations were linked in the emails (this is just a
request for comments, I'm not proposing anything -- more just seeing if
people find this useful so that I can consider proposing a more capable
boosty implementation):
SFINAE checks: http://ideone.com/RHd6FM
constexpr checks: http://ideone.com/ko09KQ
The examples are self-contained and able to be compiled/run in the browser
if you want to play around with them. Both examples have example uses at
the bottom of the file. I apologize that they are not documented --
consider them just as a proof of concept to show that the macros work.
Describing how they work is a bit complicated and I didn't feel like going
into details. If any of the magic needs clarification, let me know.
For details on how to invoke the macros linked, the basic pattern for the
SFINAE checks are:
STATIC_ASSERT_VALID
(
(int) a, // This says "given a variable a of type int..."
++a // Would the expression ++a be "valid"
);
The "invalid" expression check works similarly. Underneath the hood is an
IS_VALID_EXPR macro that has the same form and is usable on its own,
yielding a constexpr bool expression. For instance, you can use it to
easily do:
template <class T>
struct has_preincrement_operator
: std::integral_constant
use your macros at compile time to produce compile time errors, but the majority of C++ expressions have to be evaluated at run-time. So is this strictly for compile-time expressions or what ?
These are strictly compile-time checks. I find them particularly useful for concept checking and for writing unit tests.
Your original OP looked like it worked with run-time expressions ( ++a, a+b etc. ).
It is doing expression-validity checking (using C++11 extended SFINAE rules). The ++a in the example email is checking if ++a would be valid if "a" were of the specified type during substitution. A more boostified version which I have implemented locally allows the SFINAE checks to work with any number of "given" declarations and any number of expressions. It only depends on Boost.Preprocessor. -- -Matt Calabrese