Call Forwarding of a Variadic Template Base Class

In pre-11 C ++, I had something like this:

template<class T,class U,class V>
struct Foo : T,U,V {

  bool init() {

    if(!T::init() || !U::init() || !V::init())
      return false;

    // do local init and return true/false
  }
};

I would like to convert this to C ++ 11 variable syntax in order to take advantage of the flexible length argument list. I understand the concept of unpacking a list of arg templates using recursion, but I just can't figure out how the syntax is right. Here is what I tried:

template<typename... Features>
struct Foo : Features... {

  template<typename F,typename... G>
  bool recinit(F& arg,G&& ...args) {

    if(!F::init())
      return false;

    return recinit<F,G...>(args...);
  }

  bool init() {
    // how to call recinit() from here?
  }
};

I would prefer that the order of calls to the base class functions init () remains left to right, but not critical.

+5
source share
3 answers

This should work:

template<typename F, typename... T>
    struct recinit;

template<typename F>
    struct recinit<F> {
        static bool tinit(F *) {
            return true;
        }
    };
template<typename F, typename T, typename... G>
    struct recinit<F, T, G...> {
        static bool tinit(F *ptr)  {
            if (!ptr->T::init())
                return false;
            return recinit<F, G...>::tinit(ptr);
        }
    };

template<typename... Features>
struct Foo : Features... {

    bool init() {
        bool res = recinit<Foo, Features...>::tinit(this);
        //use res wisely
    }
};

, , /. Foo, , .

, , init -. , args : this! . this void*, , recinit, Foo.

, , .

+4

, - :

template<typename... Features>
struct Foo : Features...
{
    bool init()
    {
        // Courtesy of Xeo :-)
        auto il = {(static_cast<bool (Foo::*)()>(&Features::init))...};
        return std::all_of(il.begin(), il.end(), 
            [this] (bool (Foo::*f)()) { return (this->*f)(); }
            );
    }
};

, , :

template<typename... Features>
struct Foo : Features...
{
    bool init()
    {
        return combine_and((&Features::init)...);
    }

private:

    bool combine_and()
    {
        return true;
    }

    template<typename F>
    bool combine_and(F f)
    {
        return (this->*f)();
    }

    template<typename F1, typename... Fs>
    bool combine_and(F1 f1, Fs... fs)
    {
        return ((this->*f1)() && combine_and(fs...));
    }
};

, :

#include <iostream>

using namespace std;

struct A { bool init() { cout << "Hello " << endl; return true; } };
struct B { bool init() { cout << "Template " << endl; return true; } };
struct C { bool init() { cout << "World!" << endl; return true; } };

int main()
{
    Foo<A, B, C> f;
    bool res = f.init(); // Prints "Hello Template World!"
    cout << res; // Prints 1
}
+3

. -, :

return recinit<F,G...>(args...);

F, .

return recinit<G...>(args...);

( , , , .)

-, , , . G ad infinitum. , .

+2

All Articles