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

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 30 15:46:36 PDT 2018


I'd probably still vote in favor of a lambda, even if it made the iterator
type unutterable - do you have an example where that makes things
especially difficult to read?

On Mon, Jul 30, 2018 at 3:37 PM Hamza Sood via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> wrote:

> 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:
>  //
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180730/4caca891/attachment.html>


More information about the llvm-commits mailing list