C-ifying a capturing lambda What do you think of this code?

#include &lt;utility&gt;

namespace
{

template &lt;typename F, int I, typename L, typename R, typename ...A&gt;
inline F cify(L&amp;&amp; l, R (*)(A...) noexcept(noexcept(
  ::std::declval&lt;F&gt;()(::std::declval&lt;A&gt;()...))))
{
  static thread_local L l_(::std::forward&lt;L&gt;(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();

    new (static_cast&lt;void*&gt;(&amp;l_)) L(::std::forward&lt;L&gt;(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(
      ::std::declval&lt;F&gt;()(::std::forward&lt;A&gt;(args)...)))
    {
      return l_(::std::forward&lt;A&gt;(args)...);
    }
  };

  return &amp;S::f;
}

}

template &lt;typename F, int I = 0, typename L&gt;
F cify(L&amp;&amp; l)
{
  return cify&lt;F, I&gt;(::std::forward&lt;L&gt;(l), F());
}


It can be used to supply a capturing lambda as a C callback:

int main()
{
  int a;

  auto const f(cify&lt;void(*)()&gt;([a]{::std::cout &lt;&lt; "a: " &lt;&lt; a &lt;&lt; ::std::endl;}));

  f();

  return 0;
}


If you need the same callback across multiple threads, or when thread_local is unimplemented in your compiler, you can remove the thread_local keyword.

To fix the problem in the answer, one can make use of the __COUNTER__ macro. It is only one of numerous possible solutions.

std::vector&lt;void(*)()&gt; callbacks;

template &lt;int I&gt;
void add_callback (int x)
{
        callbacks.emplace_back(cify&lt;void(*)(), I&gt;([x] () { std::cout &lt;&lt; x; }));
}

int main ()
{
        add_callback&lt;__COUNTER__&gt;(1);
        add_callback&lt;__COUNTER__&gt;(2);

        for (auto&amp; callback : callbacks) {
                callback();
        }
        return 0;
}
There's an existing technique which is not dissimilar referred to as "exception vomiting". Observe:

void f(void(*p)()) {
    p();
}
template&lt;typename F&gt; void real_f(F func) {
    try {
        throw func;
    } catch(...) {
        f([] {
            try {
                throw;
            } catch(F func) {
                func();
            }
        });
    }
}


This abuses the fact that the compiler must provide a thread-local stack for complex objects for use as exception storage, regardless of their support for other thread local features, and therefore enjoys much broad compiler support. The most obvious drawbacks are a) it's horrible, and b) it's limited to stack semantics.

You could consider a less terrible version as follows assuming the relevant compiler support:

template&lt;typename F&gt; void real_f(F func) {
    thread_local std::vector&lt;std::function&lt;void()&gt;&gt; funcs;
    funcs.push_back(func);
    f([] { funcs.back()(); });
    funcs.pop_back();
}


Your cify function is nothing more than real_f as posted here, but a bit more generic and a lot less reliable as you can't handle multiple instances properly even with the use of __COUNTER__.

The general case cannot be solved without the use of a JIT to create new functions at runtime.