1

I'm using the solution proposed in this answer to get the arguments from a lambda function and it's working fine when the number of parameters is fixed. I first created a variant with one argument and would like to add a second one which accepts two arguments. I'm not looking to generalize this, just the two options below.

class MyClass {
  template<typename Lambda>
  typename std::enable_if<function_traits<Lambda>::arity, 1>>
  void Each(Lambda lambda) {
    using Traits = function_traits<decltype(lambda)>;
    using Arg0 = typename Traits::template arg<0>::type;
    lambda(Conv<Arg0>().ToType(this));
  }

  template<typename Lambda>
  typename std::enable_if<function_traits<Lambda>::arity, 2>>
  void Each(Lambda lambda) {
    using Traits = function_traits<decltype(lambda)>;
    using Arg0 = typename Traits::template arg<0>::type;
    using Arg1 = typename Traits::template arg<1>::type;
    lambda(Conv<Arg0>().ToType(this), Conv<Arg1>().ToType(this));
  }
}

void main() {
  MyClass myClass;
  myClass.Each([](int arg) {});
  myClass.Each([](int arg0, int arg1) {});
}

This code, of course, doesn't compile at all but I still don't understand how enable_if works well. I'm using GCC 6.2.0 so can't use C++17 features like if constexpr, otherwise I'd be using that. What does the correct implementation look like here?

dromodel
  • 9,581
  • 12
  • 47
  • 65
  • 4
    [What should main() return in C and C++?](https://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) – walnut Jan 05 '20 at 06:37
  • 2
    *typo*: `typename std::enable_if` should be `typename std::enable_if::type` or `std::enable_if_t`. – Jarod42 Jan 05 '20 at 08:24

1 Answers1

1

Assuming Conv is defined


class MyClass {
  public:

  template<typename Lambda>
  typename std::enable_if<(function_traits<Lambda>::arity == 1), void>::type
  Each(Lambda lambda) {
    using Traits = function_traits<decltype(lambda)>;
    using Arg0 = typename Traits::template arg<0>::type;
    lambda(Conv<Arg0>().ToType(this));
  }

  template<typename Lambda>
  typename std::enable_if<(function_traits<Lambda>::arity == 2), void>::type
  Each(Lambda lambda) {
    using Traits = function_traits<decltype(lambda)>;
    using Arg0 = typename Traits::template arg<0>::type;
    using Arg1 = typename Traits::template arg<1>::type;
    lambda(Conv<Arg0>().ToType(this), Conv<Arg1>().ToType(this));
  }
};

int main() {
  MyClass myClass;
  myClass.Each([](int arg) {});
  myClass.Each([](int arg0, int arg1) {});
  return 0;
}
Gaurav Dhiman
  • 1,163
  • 6
  • 8