问题 `std :: enable_if`是函数指针 - 怎么样?


如果用户通过,我想使用SFINAE来启用特定模板 功能指针 作为参数。

我用谷歌搜索但没有发现任何东西 - 我也试着看着 <type_traits> 文档,但找不到任何类似的东西 is_function_ptr<T>

通过函数指针,我的意思是全局函数指针,比如 TReturn(*)(TArgs...)


8153
2017-09-06 20:38


起源

你能检查is_function和is_pointer吗? - Nicolas Louis Guillemot
为什么选择SFINAE?这里太过分了。 - n.m.
为什么没有简单的f(std :: function)? - Dieter Lücking
@ n.m。,DieterLücking:我需要在编译时区分成员函数指针,函数指针和仿函数。 - Vittorio Romeo
@NicolasLouisGuillemot:我找不到一种正确的方法将两者结合起来 - 我不这么认为 is_function 适合检查函数指针(虽然我可能错了)。 - Vittorio Romeo


答案:


下面是一个类型特征,用于确定某些内容是否为函数指针和几个测试用例。注意,要测试某些东西是否是函数指针,您需要测试是否 std::is_pointer<P>::value 是 true 而如果 std::is_function<T>::value 是 true 哪里 T 是 P 删除指针。下面的代码只是这样做:

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

7
2017-09-06 22:04



你可以轻松地制造出一种特质 constexpr 功能模板和nm的答案,不是吗?它会更强大(你可能需要最少数量的参数,或特定的返回类型)。 - Ben Voigt
@BenVoigt:好的。然而,问题不是“你怎么能检测到某些东西是否是基于n.m.解决方案的函数指针”,也没有关于最小数量的参数或特定返回类型的问题。 - Dietmar Kühl
对,但是 enable_if 不关心这个特性是否是建立起来的 remove_pointer 根本没有或直接实施。 - Ben Voigt
这帮我解决了 这个问题 我的,谢谢你,+ 1。 - einpoklum


接受函数指针或成员函数指针不需要SFINAE。为了区分功能对象和不可调用的东西,需要SFINAE,可能没办法解决这个问题。

#include <utility>
#include <iostream>

template <typename Ret, typename... Parm>
void moo (Ret (*fp)(Parm...))
{
    std::cout << "funptr" << std::endl;
}

template <typename Ret, typename Owner, typename... Parm>
void moo (Ret (Owner::*fp1)(Parm...))
{
    std::cout << "memfunptr" << std::endl;
}

template <typename Funobj, typename... Parm, 
          typename Ret = 
                   decltype((std::declval<Funobj>())
                            (std::forward(std::declval<Parm>())...))>
void moo (Funobj functor)
{
    std::cout << "funobj" << std::endl;
}

void x1() {}
struct X2 { void x2() {} };
struct X3 { void operator()(){} };


int main()
{
    moo(x1);
    moo(&X2::x2);
    moo(X3());
}

4
2017-09-06 21:48