How to check at compile time that an expression is illegal?
c++, c++-concepts, sfinae, type-traits
Solution
Your question is similar to SFINAE + sizeof = detect if expression compiles.
Summary of that answer: `sizeof` evaluates the type of the expression passed to it, including instantiating a function template, but it does not generate a function call. This is the reason behind Lol4t0's observations that `sizeof(std::transform(iter1(), iter1(), iter2(), func()))` compiles even if `std::transform(iter1(), iter1(), iter2(), func())` does not.
Your concrete problem can be solved by evaluating the template from Lol4t0's answer for any output range that is to be supplied to `std::transform`. However, the general problem of verifying in a template that a function call will compile appears to be impossible to be solved with the `sizeof + SFINAE` trick. (it would require a compile-time expression that is derivable from a run-time function call).
You might want to try ConceptGCC to see if this allows you to express the requisite compile-time checking in a more convenient way.
Problem
I have a problem in my application where I'd like to assert that a function application would be rejected by the compiler. Is there a way to check this with SFINAE? For example, assume that I'd like to validate that `std::transform` to a `const` range is illegal. Here's what I have so far: ``` #include <algorithm> #include <functional> #include <iostream> namespace ns { using std::transform; template<typename Iterator1, typename Iterator2, typename UnaryFunction> struct valid_transform { static Iterator1 first1, last1; static Iterator2 first2; static UnaryFunction f; typedef Iterator2 yes_type; typedef struct {yes_type array[2];} no_type; static no_type transform(...); static bool const value = sizeof(transform(first1, last1, first2, f)) == sizeof(yes_type); }; } int main() { typedef int *iter1; typedef const int *iter2; typedef std::negate<int> func; std::cout << "valid transform compiles: " << ns::valid_transform<iter1,iter1,func>::value << std::endl; std::cout << "invalid transform compiles: " << ns::valid_transform<iter1,iter2,func>::value << std::endl; return 0; } ``` Unfortunately, my trait rejects both the legal and the illegal cases. The result: ``` $ g++ valid_transform.cpp $ ./a.out valid transform compiles: 0 invalid transform compiles: 0 ```