Substitution failure is not an error, part I

Explanation on what is SFINAE can be found at wikipedia. I’ve tried to write my own explanation but ended up with the conclusion that it’s best described there, and I wouldn’t want to copy&paste stuff. If you have any question marks floating around your heads, please don’t hesitate to ask.

SFINAE is used a lot in meta-programming. For example, you will be able to find many constructs in boost that are making use of this idea.

I’ve come across a pretty nice and complex use of SFINAE on stackoverflow the other day. The code below generates a templated class HasX, whose member HasX::value denotes whether the class T has a member (data or function) called x, or not. Let me introduce the code, and an explanation will follow.

#include <iostream>

template<typename T>
struct HasX {
    struct Fallback {
        int x;
    }; // introduce member name "x"
    struct Derived : T, Fallback { };
    template<typename C, C>
    struct ChT;
    template<typename C>
    static char (&f(ChT<int Fallback::*, &C::x>*))[1];
    template<typename C>
    static char (&f(...))[2];
    static bool const value = sizeof(f<Derived>(0)) == 2;

struct A {
    int x;

struct B {
    int y;

int main() {
    std::cout << HasX<A>::value << std::endl; // 1   
    std::cout << HasX<B>::value << std::endl; // 0

At first glance it may look like gibberish [Well, at least to gcc3.5 this code looks like gibberish – it dies with “segmentation fault” while attempting to compile. Newer versions handle it just fine, as well as visual studio], but bare with me and I shall explain it.

Just two words on why this is even remotely interesting. Note that this value is available at compile time and is fully constant. Therefore (for example), we are able to write templates with specializations that actually use (or even place compile time asserts on) what we checked for. I will leave it to the readers to think of more ways to exploit this.

Take your time: observe the code, see what you can understand for yourself. The full explanation is posted on part II.

8 thoughts on “Substitution failure is not an error, part I

  1. Obviously, it’s a very advanced topic, but I think you could somehow shorten the code to this:

    template <typename T>
    struct HasX {
        template <class C, C> struct chT;
        template <class C, class U> static char (&hasX(chT<U C::*, &C::x>*))[2];
        template <class C> static char (&hasX( ... ));
        enum { value = sizeof(hasX<T>(0)) == 2 };

    If C has a member named x the first hasX function will be chosen, otherwise the one with the elipsis will be chosen.

    Is there anything wrong with this?

    Nice post.

        1. If you meant to remove parameter U and then use (pointer-to-member) int instead of it, then it would work – but it would do something different from what we wanted.
          The version you suggest would only return true IFF there’s an _integer_ member by the name of x in the given class, not just any member (like the posted version).

  2. A few typedefs would go a long way here.

    typedef char small[1];
    typedef char big[2];
    template static small& f(ChT*);
    template static big& f(…);
    static bool const value = sizeof(f(0)) == sizeof(big);

    Much clearer what’s going on, IMHO.

Leave a Reply

Your email address will not be published. Required fields are marked *