Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I disable SFINAE?

Tags:

c++

Suppose I have this program

struct A
{
  template <typename T>
  static auto fun() -> typename T::type { }
};

struct C
{
    // doh! I forgot to add a typedef for type!
};

int main() {
    A::fun<C>();
    return 0;
}

Live example

I might need the auto specifier for any number of reasons, but the above program produces the following error:

prog.cpp:13:12: error: no matching function for call to ‘A::fun()’
  A::fun<C>();

While true, it's not particularly helpful. It's obvious in this example that I forgot to provide a C::type, but you can see that in larger programs this might become very confusing.

The real reason for the failure is buried a few lines deeper in the compiler error message:

prog.cpp:7:15: error: no type named ‘type’ in ‘struct C’

In an actual code base this message could be under hundreds or thousands (or hundreds of thousands) of lines of error messages (and above an equally large set of messages that might have arisen from another change). Considering that in a real scenario we might not even know what to look for, this could be very confusing.

An error telling me simply that the declaration of A failed because C::type was not declared would have been much more helpful.

There are of course plenty of situations where SFINAE is useful and necessary, so I don't want to somehow turn off this language feature altogether. But can I disable the SFINAE rules for this particular function?

In other words, can I add something to the function declaration to force the compiler to attempt to compile the function, and produce an error if substitution failure occurs?

like image 204
quant Avatar asked Aug 26 '14 02:08

quant


1 Answers

There is no way to disable SFINAE. C++ has no features to enable and disable at will. There is a way to make the SF part never happen, so that the E is triggered elsewhere.

struct A
{
  template <typename T>
  static auto fun() -> typename get_type<T>::type { 
    static_assert(has_type<T>::value, "Template parameter has no type member named 'type'");
  }
};

get_type (that never fails) and has_type (using SFINAE) are standard exercises described everywhere.

like image 62
n. 1.8e9-where's-my-share m. Avatar answered Oct 21 '22 09:10

n. 1.8e9-where's-my-share m.