是否有标准的静态函数包装类型模板?

时间:2016-12-24 19:14:34

标签: c++ c++14

我正在寻找一个标准的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;
}

ptr1ptr2的工作方式相似,但ptr2的大小只有一半,因为它不需要存储指向std::free的指针。

我的问题:是否采用标准库方式执行此操作,以便我无需定义fn_tfn_ref

2 个答案:

答案 0 :(得分:5)

std::integral_constant完成这项工作:

 using CFree = std::integral_constant<void (*)(void*), std::free>;

由于它可能会转换为其值,因此您可以使用相同的语法来调用operator()

Demo

答案 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;
}