函数对象转换为函数指针
Function object conversion to function pointer
我正在寻找一种将函数对象转换为函数指针的方法。
Captureless lambda 具有隐式转换,允许:
using fptr_t = int (*)(int);
fptr_t ptr = nullptr;
ptr = [](int) { return 2; };
ptr = [](auto) { return 3; };
(*ptr)(42);
我尝试对老式的空 class 函数对象做同样的事情,例如:
struct Foo {
int operator()(int) const { return 5; }
} foo;
或者像 std::less<int>
.
这样的标准谓词
我发现的一种方法是用 lambda 包装 foo
的调用。
如果我能保证 foo
是无状态的并且是常量
我真的不需要 this 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
,但它有点重,而我正在尝试获得轻量级的解决方案。
感谢任何建议。
我相信您可以通过以下方式简化 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{}
,这对我来说似乎更干净。
我正在寻找一种将函数对象转换为函数指针的方法。 Captureless lambda 具有隐式转换,允许:
using fptr_t = int (*)(int);
fptr_t ptr = nullptr;
ptr = [](int) { return 2; };
ptr = [](auto) { return 3; };
(*ptr)(42);
我尝试对老式的空 class 函数对象做同样的事情,例如:
struct Foo {
int operator()(int) const { return 5; }
} foo;
或者像 std::less<int>
.
我发现的一种方法是用 lambda 包装 foo
的调用。
如果我能保证 foo
是无状态的并且是常量
我真的不需要 this 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
,但它有点重,而我正在尝试获得轻量级的解决方案。
感谢任何建议。
我相信您可以通过以下方式简化 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{}
,这对我来说似乎更干净。