为什么 std::is_invocable 不接受非类型模板参数

Why doesn't std::is_invocable accept a non type template parameter

我最近偶然发现 std::is_invocable 将被引入 C++17 标准,我想知道为什么它需要用户为函数指针提供类型而不是仅仅提供函数指针本身,这可能更方便,特别是因为非类型模板参数现在可以不受约束。

我的意思可以在下面的例子中解释

void hello_world() {
    cout << "Hello world" << endl;
}
int main() {
    cout << std::is_invocable_v<decltype(hello_world)> << endl;
    // as opposed to being able to do
    // cout << std::is_invocable_v<hello_world> << endl;

    return 0;
}

std::is_invocable 的主要用途是与类型和模板参数一起使用。不是只能通过直接使用函数指针来使用。

让我们稍微更改一下您的代码并添加一个有用的案例:

void callF(F function, Args&& args) {
    std::invoke(function, std::forward<Args>(args)...);
}

// Later, in your main

callF(hello_world);

您想过滤您的函数,使其在调用无效时不可调用。您可以像这样使用 std::is_invokable

auto callF(F function, Args&& args) -> std::enable_if<std::is_invocable_v<F, Args...>> {
    std::invoke(function, std::forward<Args>(args)...);
}

如您所见,作为参数发送到 std::is_invocable 的类型反映了发送到 std::invoke.

的参数

作为奖励,支持的不仅仅是函数指针。也支持函数对象,甚至支持成员函数指针。现在,您可以像这样使用 callF 函数:

callF([](int i){ /* ... */ }, 8);

struct Test { void test() {} };

Test t;

callF(&Test::test, t);

I am wondering why it needs a user to provide a type for a function pointer as opposed to just providing the function pointer itself which might be more convenient

因为您总是 具有要测试的可调用对象的类型,但您并不总是具有value 把它当作常量表达式。当然,当你确实有值时,你必须写出 decltype(foo) 而不是 foo,但这似乎是一个相当小的负担,并且会涵盖相当大比例的用例。不确定增加 template <auto F, class... Args> is_invocable 的复杂性是否值得,有时,作为用户的您不必编写 decltype.