[PATCH] D50021: [ADT] Add a static function pointer type

Hamza Sood via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 30 15:37:01 PDT 2018


hamzasood created this revision.
hamzasood added reviewers: dexonsmith, fhahn, chandlerc, timshen.
Herald added a subscriber: llvm-commits.

This patch adds a simple type that lets you create a functor from a function at compile time.

While working on Clang, I needed a way to create an `llvm::filter_iterator` that filters based on the dynamic type as determined by `llvm::isa`. As far as I'm aware, the best way to do this currently (without lambdas as they'd make the iterator type unutterable) is:

  llvm::make_filter_range(MyRange, static_cast<bool(*)(Base *)>(&isa<Derived>))

That's problematic because the iterator object ends up storing a function pointer; if the compiler can't follow the iterator's path from creation to use then it probably won't be able to get round the unnecessary indirection. This new type solves that by storing the function address as part of the object type, so there's no runtime overhead.


Repository:
  rL LLVM

https://reviews.llvm.org/D50021

Files:
  include/llvm/ADT/STLExtras.h
  unittests/ADT/STLExtrasTest.cpp


Index: unittests/ADT/STLExtrasTest.cpp
===================================================================
--- unittests/ADT/STLExtrasTest.cpp
+++ unittests/ADT/STLExtrasTest.cpp
@@ -364,4 +364,21 @@
   EXPECT_EQ(5, count);
 }
 
+int g() { return 42; }
+void g(int &&) { }
+
+TEST(STLExtrasTest, static_fptr) {
+  {
+    static_fptr<int(), g> obj;
+    EXPECT_EQ(obj(), 42);
+  }
+
+  // Check for perfect forwarding of the parameters.
+  {
+    static_fptr<void(int &&), g> obj;
+    int i = 0;
+    obj(std::move(i));
+  }
+}
+
 } // namespace
Index: include/llvm/ADT/STLExtras.h
===================================================================
--- include/llvm/ADT/STLExtras.h
+++ include/llvm/ADT/STLExtras.h
@@ -135,6 +135,26 @@
   operator bool() const { return callback; }
 };
 
+/// A simple functor that just calls a function specified at compile time.
+/// Unlike storing a function pointer, this has zero runtime overhead because
+/// the function address is part of the object type.
+///
+/// Example usage:
+///     void f();
+///
+///     static_fptr<void(), f> obj;
+///     obj();
+template<typename T, T *Fn,
+         typename = typename std::enable_if<std::is_function<T>::value>::type>
+struct static_fptr {
+  template<typename... Args>
+  auto operator()(Args &&... args) const
+      noexcept(noexcept(Fn(std::forward<Args>(args)...)))
+      -> decltype(Fn(std::forward<Args>(args)...)) {
+    return Fn(std::forward<Args>(args)...);
+  }
+};
+
 // deleter - Very very very simple method that is used to invoke operator
 // delete on something.  It is used like this:
 //


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50021.158094.patch
Type: text/x-patch
Size: 1599 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180730/d04d306e/attachment.bin>


More information about the llvm-commits mailing list