C++ 为什么';t std::是否可以接受非类型模板参数

C++ 为什么';t std::是否可以接受非类型模板参数,c++,templates,c++17,non-type,C++,Templates,C++17,Non Type,我最近偶然发现,C++17标准将引入这一点,我想知道为什么它需要用户为函数指针提供类型,而不是只提供函数指针本身,这可能更方便,特别是因为非类型模板参数现在可以不受约束 我的意思可以在下面的例子中解释 void hello_world() { cout << "Hello world" << endl; } int main() { cout << std::is_invocable_v<decltype(hello_world)>

我最近偶然发现,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;
}
void hello\u world(){

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

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

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

// Later, in your main

callF(hello_world);
如您所见,作为参数发送到
std::is\u invocable
的类型反映了发送到
std::invoke
的参数

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

auto callF(F function, Args&& args) -> std::enable_if<std::is_invocable_v<F, Args...>> {
    std::invoke(function, std::forward<Args>(args)...);
}
callF([](int i){ /* ... */ }, 8);

struct Test { void test() {} };

Test t;

callF(&Test::test, t);
我想知道为什么它需要用户为函数指针提供一个类型,而不是仅仅提供函数指针本身,这可能更方便


因为您总是有要测试的可调用类型,但并不总是将其值作为常量表达式。当然,当您有值时,您必须写出
decltype(foo)
而不仅仅是
foo
,但这似乎是一个相当小的负担,并且将覆盖相当多的用例。不确定是否值得拥有一个
模板的额外复杂性,因为它是不可撤销的
,只是为了有时候,作为用户,您不必因为传递函数点而编写
decltype

er作为模板参数将导致鸡对蛋的问题,请参见(不要觉得这一个实际上是一个傻瓜)。您必须将函数的类型定义为第一个模板参数,但您需要剩余的模板参数。一个是类型,另一个是值。@SamVarshavchik Dude,你在说什么?C++17,
模板自动