Как получить тип возвращаемого значения и тип параметра обобщенной лямбды c? - PullRequest
1 голос
/ 01 апреля 2020

Я хочу получить тип возврата и тип параметра лямбды. Можно ли определить тип параметра и тип возврата лямбды? дать решение. Но оно не работает для generi c лямбда.

template<typename F>
struct function_traits :public
    function_traits<decltype(&F::operator())> {};

template<typename R,typename C,typename... Args>
struct function_traits<R(C::*)(Args...)const>:public
    function_traits<R(Args...)>{
  constexpr static size_t arity = sizeof...(Args);
};

auto f1 = [](int x) {return x+1; };
Print(function_traits<decltype(f1)>::arity);  //return 1
auto f2 = [](auto x) {return x+1; };
Print(function_traits<decltype(f2)>::arity);  //error

Так как решить, чтобы получить тип возвращаемого значения и тип параметра обобщенного c лямбда?

Ответы [ 2 ]

3 голосов
/ 01 апреля 2020

Generi c лямбды - это лямбды, где перегрузка operator() является функцией шаблона. Если выводится параметр функции шаблона, то он не имеет типа; только отдельный экземпляр такого шаблона имеет параметр с типом.

auto не является типом; это заполнитель, что означает «это параметр шаблона».

1 голос
/ 01 апреля 2020

Лямбды никоим образом не являются функциями.

Компилятор обрабатывает f1 и f2, как если бы они были классами с операторами вызова.

Некоторые лямбды имеют неявные операторы преобразования в функцию указатели.

Вот ссылка на то, как эти двое выглядят в cppinsights.

Кстати, я сильно рекомендую использовать cppinsights если вы новичок в шаблонах C ++. Вот отличное видео о нем и вот один , где он использует cppinsights для глубокого изучения лямбд.

Я также скопировал соответствующий код здесь для объяснение, и в случае, если ссылка исчезнет.

Вот как выглядит ваш f1.

class __lambda_1_11
{
  public: 
  inline /*constexpr */ int operator()(int x) const
  {
    return x + 1;
  }

  using retType_1_11 = int (*)(int);
  inline /*constexpr */ operator retType_1_11 () const noexcept
  {
    return __invoke;
  };

  private: 
  static inline int __invoke(int x)
  {
    return x + 1;
  }
};

, и так выглядит ваш f2.

class __lambda_2_11
{
  public: 
  template<class type_parameter_0_0>
  inline /*constexpr */ auto operator()(type_parameter_0_0 x) const
  {
    return x + 1;
  }
  private: 
  template<class type_parameter_0_0>
  static inline auto __invoke(type_parameter_0_0 x)
  {
    return x + 1;
  }
};

Обратите внимание, что f1 имеет не шаблонный оператор вызова и имеет оператор неявного преобразования в указатель на функцию (int (*)(int)).

f2 имеет оператор вызова шаблона и не имеет оператора неявного преобразования - потому что оператор вызова является шаблоном функции-члена.

...