Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`std::enable_if` is function pointer - how?

I want to use SFINAE to enable a particular template if the user passes a function pointer as a parameter.

I have googled around but found nothing - I also tried looking at the <type_traits> documentation but couldn't find anything that resembled a is_function_ptr<T>.

By function pointer, I mean global function pointers, like TReturn(*)(TArgs...).

like image 869
Vittorio Romeo Avatar asked Sep 06 '13 20:09

Vittorio Romeo


People also ask

Is std :: function a function pointer?

They are not the same at all. std::function is a complex, heavy, stateful, near-magic type that can hold any sort of callable entity, while a function pointer is really just a simple pointer. If you can get away with it, you should prefer either naked function pointers or auto - bind / auto -lambda types.

How can a function pointer be declared?

You can use a trailing return type in the declaration or definition of a pointer to a function. For example: auto(*fp)()->int; In this example, fp is a pointer to a function that returns int .

How do you call a function from a pointer?

Calling a function using a pointer is similar to calling a function in the usual way using the name of the function. int length = 5; // Different ways to call the function // 1. using function name int area = areaSquare(length); // 2. using function pointer (a) int area = (*pointer)(length); // 3.

What is std :: Enable_if?

std::enable_if can be used in many forms, including: as an additional function argument (not applicable to operator overloads) as a return type (not applicable to constructors and destructors) as a class template or function template parameter.


1 Answers

Below is a type trait determining if something is a function pointer and a couple of test cases. Note, that to test if something is a function pointer, you need to test if std::is_pointer<P>::value is true and if std::is_function<T>::value is true where T is P with the pointer removed. The code below just does that:

#include <type_traits>
#include <iostream>
#include <utility>

template <typename Fun>
struct is_fun_ptr
    : std::integral_constant<bool, std::is_pointer<Fun>::value
                            && std::is_function<
                                   typename std::remove_pointer<Fun>::type
                               >::value>
{
};

template <typename Fun>
typename std::enable_if<is_fun_ptr<Fun>::value>::type
test(Fun) {
    std::cout << "is a function pointer\n";
}

template <typename Fun>
typename std::enable_if<!is_fun_ptr<Fun>::value>::type
test(Fun) {
    std::cout << "is not a function pointer\n";
}

void f0() {}
void f1(int) {}
void f2(int, double) {}

struct s0 { void operator()() {} };
struct s1 { void operator()(int) {} };
struct s2 { void operator()(int, double) {} };

int main()
{
    int v0(0);
    int* p0(&v0);
    void (*p1)() = &f0;
    void (**p2)() = &p1;
    std::cout << "v0="; test(v0);
    std::cout << "p0="; test(p0);
    std::cout << "p1="; test(p1);
    std::cout << "p2="; test(p2);

    std::cout << "f0="; test(&f0);
    std::cout << "f1="; test(&f1);
    std::cout << "f2="; test(&f2);

    std::cout << "s0="; test(s0());
    std::cout << "s1="; test(s1());
    std::cout << "s2="; test(s2());

    std::cout << "l0="; test([](){});
    std::cout << "l1="; test([](int){});
    std::cout << "l2="; test([](int, double){});
}
like image 58
Dietmar Kühl Avatar answered Oct 02 '22 05:10

Dietmar Kühl