Why does `std::is_function_v` not work as expected?

Viewed 505
#include <iostream>
#include <type_traits>
#include <iomanip>

using namespace std;

template<typename T>
bool f(T&& v)
{
    return is_function_v<decltype(forward<T>(v))>;
}

int main()
{
    cout << boolalpha
        << is_function_v<decltype(setw)>
        << endl;

    cout << boolalpha
        << f(setw)
        << endl;

    return 0;
}

The outout is: (clang 6.0 & gcc 8.0)

>

true

false

But the result I expect should be:

>

true

true

Why does std::is_function_v not work as expected?

1 Answers

You need to remove reference on T.

template<typename T>
bool f(T&& v)
{
    return is_function_v<remove_reference_t<decltype(forward<T>(v))>>;
    //                   ~~~~~~~~~~~~~~~~~~
}

When pass setw to f, it's an lvalue, then the forwarding reference type T will be deduced as an lvalue reference to function. For std::is_function, references to function (and pointers to function etc) don't count as function types.


BTW: the forwarding reference type T will be deduced as either lvalue reference or rvalue reference; and using decltype on std::forward would always yield a reference type, either lvalue reference or rvalue reference.

Related