Is there a standard static function template template?

I am looking for a standard template like C ++ 14, which statically (at compile time) introduces a link to a function as an argument to a template and implements it operator()as a call forwarding function.

I know that std::functionexists, but it stores a pointer to a function as a data element. I want the function reference to be embedded in the type signature so that the wrapper type is empty and default construct.

I have a working implementation (with an example use):

#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;
}

ptr1and ptr2work the same, but ptr2half the size, because it does not need to keep a pointer to std::free.

: , fn_t fn_ref?

+4
2

std::integral_constant, :

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

, operator().

+5

: .

, ( ) .

, :

#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;
}
+1

Source: https://habr.com/ru/post/1664791/


All Articles