void f(int) 的模板和 decltype

template and decltype for void f(int)

我正在学习使用 C++11 编写自己的特征,仅借用 std::true_typestd::false_type

我创建了以下特征:

#include <iostream>

template <typename F>
struct is_farg1: std::false_type {};

template <typename R, typename A>
struct is_farg1<R (*)(A)> : std::true_type {};

现在考虑一个包含上述特征和以下代码的程序:

void f(int) {}

int main() {
    std::cout << "is_farg1<decltype(f)>  : " << is_farg1<decltype(f)>::value << std::endl;
    std::cout << "is_farg1<void(*)(int)> : " << is_farg1<void(*)(int)>::value << std::endl;

    return 0;
}

它产生以下输出:

is_farg1<decltype(f)>  : 0
is_farg1<void(*)(int)> : 1

我的问题:

  1. 为什么 is_farg1<void(*)(int)>::valuetrueis_farg1<decltype(f)>::value 返回 false
  2. 如果我的 trait 写错了那么我如何检查给定函数是否只有一个参数以便我也可以使用 decltype(f)?

因为 decltype(f) 给出了确切的函数类型(即 void(int))而不是函数指针类型(即 void(*)(int))。当decltype用于实体时,

If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression.

您可以为函数类型添加另一个特化,例如

template <typename R, typename A>
struct is_farg1<R (A)> : std::true_type {};

LIVE

或者像函数指针一样检查类型

is_farg1<decltype(f)*>::value
//                  ^

// or
is_farg1<decltype(&f)>::value
//                ^

LIVE