Is_function_pointer <> для <type_traits>

Есть они в <type_traits>:

is_pointer<>
is_function<>
is_member_function_pointer<>

Но не это:

is_function_pointer<>

Почему это так?

Ответ 1

Черты в [meta.unary.cat] предназначены для классификации каждого типа в одну категорию. Является ли это пустотой, интегралом, указателем и т.д. На этом уровне указатель на функцию не отличается от указателя на int. И обратите внимание, что указатель на элемент не является указателем. Это всего лишь английский омоним.

Предполагалось, что каждый тип возвращает true только для одного признака в [meta.unary.cat]. И в этой категоризации, как указатель на функцию, так и скалярный указатель будут возвращать true в is_pointer.

Отмечу, что мы не достигли нашей цели. nullptr_t ускользает от нашей цели. Но мы приблизились. Здесь - графическое представление текущей классификации type_traits.

Update:

Это правильно работающая программа с правильным выходом:

#include <iostream>
#include <type_traits>

typedef void (*fptr)();
typedef int* intptr;

int main()
{
    std::cout << std::is_function<fptr>::value << '\n';
    std::cout << std::is_pointer<fptr>::value << '\n';
    std::cout << std::is_pointer<intptr>::value << '\n';
}

0
1
1

Ответ 2

Кажется, это странный надзор. Однако указатели-члены всегда являются типами указателей-членов, в отличие от бесплатных функций, которые могут быть либо типами указателей (void(*)()), либо типами функций (void()). Кроме того, std::is_pointer никогда не возвращает true для типов указателей-членов.

Однако, если вам нужна эта функциональность, вот реализация:

template<typename testType>
struct is_function_pointer
{
    static const bool value =
        std::is_pointer<testType>::value ?
        std::is_function<typename std::remove_pointer<testType>::type>::value :
        false;
};