Время жизни лямбда-объектов относительно преобразования указателя на функцию

Следующийэтот ответ Теперь мне интересно, каковы правила для времени жизни лямбды и как они соотносятся с временем жизни указателей на функции, которые создаются автоматическим преобразованием. Есть несколько вопросов о времени жизни лямбд (например,Вот а такжеВот), в этом случае ответы «они ведут себя точно так же, как вы сами написали полный объект функтора», однако ни один из них не обращается к преобразованию в указатель на функцию, что вполне может быть особым случаем.

Я собрал этот небольшой рабочий пример, который иллюстрирует мою озабоченность:

#include <iostream>

typedef int (*func_t)(int);

// first case
func_t retFun1() {
  static auto lambda = [](int) { return 1; };
  // automatically converted to func_t
  return lambda;
}

// second case
func_t retFun2() {
  // no static
  auto lambda = [](int) { return 2; };
  // automatically converted to func_t and 
  // the local variable lambda reaches the end of its life
  return lambda;
}

int main() {
  const int a = retFun1()(0);
  const int b = retFun2()(0);
  std::cout << a << "," << b << std::endl;
  return 0;
}

Это хорошо определено для обоих случаев? Или только дляretFun1()? Вопрос заключается в том, «является ли та функция, на которую указывает указатель функции, необходимой для вызова самого объекта функтора или для переопределения тела в отдельной функции?» Любой из них может иметь смысл, но тот факт, что преобразование в указатель на функцию, в частности, требует лямбда без захвата, наводит на мысль, что это может быть последний.

Другими словами, я вижу по крайней мере два разумных способа, которыми компилятор может захотеть реализовать такие лямбды. Одной из возможных, легальных реализаций может быть компилятор для синтеза кода, подобного следующему:

func_t retFun3() {
  struct __voodoo_magic_lambda_implementation {
    int operator()(int) const {
      return 3;
    }
    static int plainfunction(int) {
      return 3;
    }
    operator func_t() const {
      return plainfunction;
    }
  } lambda;
  return lambda;
}

в этом случае обаstatic и неstatic вариантыretFun было бы хорошо. Однако, если для компилятора также допустимо реализовывать лямбду, например:

static int __voodoo_impl_function(int x);
static struct __voodoo_maigc_impl2 {
  int operator()(int) const {
    return 4;
  }
  operator func_t() const {
    return __voodoo_impl_function;
  }
} *__magic_functor_ptr;
static int __voodoo_impl_function(int x) {
  return (*__magic_functor_ptr)(x);
}

func_t retFun4() {
  __voodoo_maigc_impl2 lambda;
  // non-static, local lifetime
  __magic_functor_ptr = &lambda; //Or do the equivalent of this in the ctor
  return lambda;
}

тогдаretFun2() является неопределенным поведением.

Ответы на вопрос(1)

Ваш ответ на вопрос