2

I am looking for a way to convert function object to function pointer. Captureless lambda has implicit conversion that allows to:

using fptr_t = int (*)(int);
fptr_t ptr = nullptr;
ptr = [](int) { return 2; };
ptr = [](auto) { return 3; };
(*ptr)(42);

I try to do the same with old-fashioned, empty class function objects like:

struct Foo {
  int operator()(int) const { return 5; }
} foo;

Or std predicates like std::less<int>.

One way I found is to wrap call of foo with lambda. If I can assure that foo is stateless and const I dont really need this ptr and lambda-capture:

template <typename R, typename... Args>
struct to_function_pointer<R(Args...)> {
private:
  template <typename T, REQUIRES(std::is_empty<T>::value)>
  static T const& stateless_const() {
    return (*static_cast<T const*>(nullptr));
  }

public:
  using pointer = R (*)(Args...);

  template <typename U>
  pointer operator()(U) const {
    return [](Args... args) {
      return stateless_const<std::decay_t<U>>()(args...);
    };
  }
};

But here I do not know how to provide perfect forwarding, cause [](Args&&...) or [](auto&&...) cannot convert to R(*)(Args...). Such trick fails when args is noncopyable like std::unique_ptr<int>.

I know that I could use std::function, but it's kind of heavy-weight, while I am trying to get a light-weight solution.

Live example.

Any advice appreciated.

4

1 回答 1

3

我相信您可以通过以下方式简化您to_function_pointer的:

template <typename R, typename... Args>
struct to_function_pointer<R(Args...)> {
    using pointer = R(*)(Args...);

    template <typename U, REQUIRES(std::is_empty<U>::value && std::is_trivially_constructible<U>::value)>
    pointer operator()(U ) const
    {
        return [](Args... args) {
            return U{}(std::forward<Args>(args)...);
        }
    }
};

有几点需要注意。Args...是否已经是参考文献,您正在提供该签名。所以forward<>仍然会做同样的事情——这个函数恰好不是这里的模板。另外,废弃奇怪的nullptr演员阵容。这看起来很糟糕——如果我们只需要微不足道的可构造性,我们就可以写出U{}对我来说看起来更干净的东西。

于 2015-10-08T20:28:23.790 回答