dimanche 27 mars 2016

SFINAE used recursively

Consider this code:

#include <iostream>

struct A {
    void foo() const {std::cout << "A::foo()\n";}
};

struct B {
    A value;
    void foo() const {std::cout << "B::foo()\n";}
};

struct C {
    B value;
    void foo() const {std::cout << "C::foo()\n";}
};

struct D {
    C value;
};

struct Default {
    Default(...) {}
};

template <typename T>
void fooValue (const T& t, Default) {
    t.foo();
}

template <typename T, typename = decltype(T::value)>
void fooValue (const T& t, int) {
    fooValue(t.value, 0);
}

template <typename T>
void foo (const T& t) {
    fooValue(t, 0);
}

int main() {
    const D d;
    foo(d);  // A::foo()
}

So A::foo() is outputted because A is the last type in the chain that has a value member. I want to now define

template <std::size_t N, typename T> void foo (const T&)

so that N = 0 will do the same thing, but N = 1 will have the second last type in the chain call its foo() function, N = 2 will have the third last type in the chain call its foo() function, etc... Thus in the example above, foo<1>(d); will output B::foo() and foo<2>(d); will output C::foo(). But I can't think of how to implement this. Can anyone help here?

Aucun commentaire:

Enregistrer un commentaire