Variadic Template Functor Call

623 views Asked by At

So I've been trying to use variadic templates to compose objects out of more convenient subtypes, but I'm having trouble getting it to do exactly what I want.

template<class ...Functor>
struct SeqMethod:public Functor...{
  template<class F>
  void call(F& a){
    F::operator()();
  }
  template<class F,class ... funcs>
  void call(){
    F::operator()();

    call<funcs...>();
  }
  public:
  void operator()(){
    call<Functor...>();
  }
};

This isn't valid syntax, so there's that.

Ideally I'd like to be able to use something like this

class A{
public:
  void operator()(){
    std::cout<<"A";
  }
};
class B{
public:
  void operator()(){
    std::cout<<"B";
  }
};

class C:public SeqMethod<A,B>{};

Which in this case should output "AB", and in general be suitable for composing behaviors together.

2

There are 2 answers

1
Sam Varshavchik On BEST ANSWER

The easiest way to do this is with C++17's fold expressions:

template<class ...Functor>
struct SeqMethod:public Functor...{

 public:
    void operator()(){
        (Functor::operator()(),...);
    }
};

class A{
public:
    void operator()(){
        std::cout<<"A";
    }
};
class B{
public:
    void operator()(){
        std::cout<<"B";
    }
};

class C:public SeqMethod<A,B>{};

int main()
{
    C c;
    c();
    return 0;
}

Output (tested with gcc 6.2):

AB
3
skypjack On

You don't actually need any call member function in your case.
Instead you can do this in C++11/C++14:

template<class ...Functor>
struct SeqMethod:public Functor...{
  public:
  void operator()(){
      int _[] = { (Functor::operator()(), 0)... };
      return void(_);
  }
};

It follows a minimal, working example:

#include<iostream>

template<class ...Functor>
struct SeqMethod:public Functor...{
  public:
  void operator()(){
    int _[] = { (Functor::operator()(), 0)... };
    return void(_);
  }
};

class A{
public:
  void operator()(){
    std::cout<<"A";
  }
};
class B{
public:
  void operator()(){
    std::cout<<"B";
  }
};

class C:public SeqMethod<A,B>{};

int main() {
  C c;
  c();
}