函数对象转换为函数指针

时间:2015-10-08 19:47:40

标签: c++ c++11 lambda function-pointers function-object

我正在寻找一种将函数对象转换为函数指针的方法。 无捕捉lambda具有隐式转换,允许:

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

我尝试对老式的空类函数对象执行相同的操作,例如:

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

或std谓词如std::less<int>

我找到的一种方法是用lambda包装foo的调用。 如果我能确保foo是无状态和常量 我真的不需要这个 ptr和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...);
    };
  }
};

但在这里我不知道如何提供完美的转发, 原因[](Args&&...)[](auto&&...)无法转换为R(*)(Args...)。 当args像std::unique_ptr<int>一样不可复制时,这种技巧就会失败。

我知道我可以使用std::function,但它有点重量级,而我正试图获得轻量级的解决方案。

Live example

任何建议表示赞赏。

1 个答案:

答案 0 :(得分: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{}这对我来说似乎更清洁了。