
On 04/12/11 17:20, Jeremiah Willcock wrote:
On Sun, 4 Dec 2011, Dave Abrahams wrote:
I don't know whether this is actually possible, but I was thinking today that there might be a way to use the new SFINAE to detect errors in a large class of invalid expressions without actually causing a hard error, and thereby build an assertion that fails compilation when passed a valid expression and passes for any invalid expression in the large class mentioned above.
Any takers?
Here's the best I've been able to come up with. It works on GCC 4.6 (I tested with a prerelease, so the bug I mention might have been fixed). It only works within classes, and you need to use a separate template parameter in the tested expression (it would be nice if you could shadow template parameters in a nested class, BTW).
Both responses to this request so far have given an example where the expression uses types, rather than values. I think we can do better if we use values, precisely because we can shadow value names, where we can't shadow template parameters. Again, I can only make it work in a class context. For example, the following code can be made to do the right thing: template<typename T, typename U> struct A { T x; U y; ASSERT_INVALID_EXPR((x), x+y, "Can add x and y; bad"); }; int main() { A<char*, char*>(); A<int, int>(); // generates assertion failure } Here the second argument to ASSERT_INVALID_EXPR is the expression, and the first is a PP_SEQ of some values used in it (enough such that every sub-expression which might be invalid uses one of the values). So, instead of "(x)", we could have passed "(x)(y)" here and it would have worked just as well. The macro in this case expands to something which is essentially: struct invalid_expr_test { template<typename T0> static boost::mpl::false_ is_ok(int*, T0&& x, decltype(x+y)* = 0); template<typename T0> static boost::mpl::true_ is_ok(bool, T0&&); typedef decltype(is_ok((int*)0, x)) test_type; }; static_assert(invalid_expr_test::test_type::value, "Can add x and y; shouldn't be able to");; By shadowing the specified variable names (in this case x) we make the expression a type-dependent expression, and avoid the hard error. I attach the implementation with all the gory preprocessor metaprogramming details. Tested with g++ 4.5.2, g++ 4.6.2, and clang++ trunk 143505. John Bytheway