我正在寻找一个标准的C ++ 14类型模板,静态地(在编译时)将函数引用嵌入作为模板参数,并实现operator()
作为对引用函数的转发调用。
我知道std::function
存在,但它将函数指针存储为数据成员。我希望函数引用嵌入在类型签名中,以便包装类型为空和 default-constructible 。
我有一个有效的实现(使用示例用例):
#include <cstring>
#include <iostream>
#include <memory>
// Implementation:
template <typename Ret, typename... Args>
struct fn_t {
template <Ret (Func)(Args...)>
struct fn_ref {
Ret operator () (Args &&...args) const {
return Func(std::forward<Args>(args)...);
}
};
};
// Example use case:
template <typename T>
using unique_c_ptr = std::unique_ptr<T, fn_t<void, void *>::fn_ref<std::free>>;
int main() {
// { char *, void (*)(void *) } (16 bytes)
std::unique_ptr<char[], decltype(&std::free)> ptr1(::strdup("Hello"), &std::free);
// { char *, fn_t<void, void *>::fn_ref<std::free> } (8 bytes)
unique_c_ptr<char[]> ptr2(::strdup("Hello"));
std::cout << sizeof ptr1 << '\n' // 16
<< sizeof ptr2 << std::endl; // 8
return 0;
}
ptr1
和ptr2
的工作方式相似,但ptr2
的大小只有一半,因为它不需要存储指向std::free
的指针。
我的问题:是否采用标准库方式执行此操作,以便我无需定义fn_t
和fn_ref
?
答案 0 :(得分:5)
有std::integral_constant
完成这项工作:
using CFree = std::integral_constant<void (*)(void*), std::free>;
由于它可能会转换为其值,因此您可以使用相同的语法来调用operator()
。
答案 1 :(得分:1)
简短的回答是,不。
但有人可能会说,它更简洁(甚至可能需要更少的击键次数)来创建一个简单的仿函数类型来调用你想要的函数。
我的感觉是这更容易推理:
#include <cstring>
#include <iostream>
#include <memory>
// Implementation:
struct invoke_free
{
void operator()(void*p) const noexcept {
std::free(p);
}
};
template <typename T>
using unique_c_ptr = std::unique_ptr<T, invoke_free>;
// Example use case:
int main() {
// { char *, fn_t<void, void *>::fn_ref<std::free> } (8 bytes)
unique_c_ptr<char[]> ptr2(::strdup("Hello"));
std::cout << sizeof ptr2 << std::endl; // 8
return 0;
}