[PATCH] Add llvm::function_ref as a type-erased non-owning reference to a callable

Richard Smith richard at metafoo.co.uk
Mon May 5 18:12:05 PDT 2014


On Mon, May 5, 2014 at 4:43 PM, Rafael EspĂ­ndola <rafael.espindola at gmail.com
> wrote:

> > Revised patch attached. This also converts optimizeGlobalCtorsList to use
> > function_ref.
>
> I would probably keep isEmptyFunction as a stand alone function with a
> comment instead of converting it to a lambda.
>

Committed with this change in r208025.


> This is quiet handy, it should have an entry in the ProgrammersManual.
>

Proposed documentation patch attached.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140505/04166546/attachment.html>
-------------- next part --------------
Index: docs/CodingStandards.rst
===================================================================
--- docs/CodingStandards.rst	(revision 208026)
+++ docs/CodingStandards.rst	(working copy)
@@ -108,6 +108,8 @@
 * Lambdas: N2927_
 
   * But *not* ``std::function``, until Clang implements `MSVC-compatible RTTI`_.
+    In many cases, you may be able to use ``llvm::function_ref`` instead, and it
+    is a superior choice in those cases.
   * And *not* lambdas with default arguments.
 
 * ``decltype``: N2343_
Index: docs/ProgrammersManual.rst
===================================================================
--- docs/ProgrammersManual.rst	(revision 208026)
+++ docs/ProgrammersManual.rst	(working copy)
@@ -263,6 +263,78 @@
 when defining a function which should be able to efficiently accept concatenated
 strings.
 
+.. _function_apis:
+
+Passing functions and other callable objects
+--------------------------------------------
+
+Sometimes you may want a function to be passed a callback object. In order to
+support lambda expressions and other function objects, you should not use the
+traditional C approach of taking a function pointer and an opaque cookie:
+
+.. code-block:: c++
+
+    void takeCallback(bool (*Callback)(Function *, void *), void *Cookie);
+
+Instead, use one of the following approaches:
+
+Function template
+^^^^^^^^^^^^^^^^^
+
+If you don't mind putting the definition of your function into a header file,
+make it a function template that is templated on the callable type.
+
+.. code-block:: c++
+
+    template<typename Callable>
+    void takeCallback(Callable Callback) {
+      Callback(1, 2, 3);
+    }
+
+The ``function_ref`` class template
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``function_ref``
+(`doxygen <http://llvm.org/doxygen/classllvm_1_1function_ref.html>`__) class
+template represents a reference to a callable object, templated over the type
+of the callable. This is a good choice for passing a callback to a function,
+if you don't need to hold onto the callback after the function returns.
+
+``function_ref<Ret(Param1, Param2, ...)>`` can be implicitly constructed from
+any callable object that can be called with arguments of type ``Param1``,
+``Param2``, ..., and returns a value that can be converted to type ``Ret``.
+For example:
+
+.. code-block:: c++
+
+    void visitBasicBlocks(Function *F, function_ref<bool (BasicBlock*)> Callback) {
+      for (BasicBlock &BB : *F)
+        if (Callback(&BB))
+          return;
+    }
+
+can be called using:
+
+.. code-block:: c++
+
+    visitBasicBlocks(F, [&](BasicBlock *BB) {
+      if (process(BB))
+        return isEmpty(BB);
+      return false;
+    });
+
+Note that a ``function_ref`` object contains pointers to external memory, so
+it is not generally safe to store an instance of the class (unless you know
+that the external storage will not be freed).
+``function_ref`` is small enough that it should always be passed by value.
+
+``std::function``
+^^^^^^^^^^^^^^^^^
+
+You cannot use ``std::function`` within LLVM code, because it is not supported
+by all our target toolchains.
+
+
 .. _DEBUG:
 
 The ``DEBUG()`` macro and ``-debug`` option


More information about the llvm-commits mailing list