Передача функции указателя на член в шаблон - PullRequest
0 голосов
/ 28 июня 2018

Интересно, как я могу передать указатель на нестатическую функцию-член в шаблон? Вот упрощенный код:

template<typename, typename>
struct contains;

template<typename T, typename R, typename... Ts>
struct contains<T, R(Ts...)>
{
    static constexpr bool result = std::disjunction_v<std::is_same<T, Ts>...>;
};

class A
{
public:
    static void staticFoo(int a, double* b) {}
    void foo(int a, double* b) {}
};
void foo(int a, double* b) {}

int main ()
{
    //ok, this works
    std::cout << std::boolalpha << contains<double*, decltype(foo)>::result;
    //this too
    std::cout << std::boolalpha << contains<double*, std::remove_pointer_t<decltype(&A::staticFoo)>>::result;
    //boom, error
    std::cout << std::boolalpha << contains<double*, decltype(&A::foo)>::result;

    return 0;
}

При выполнении этого кода я получил ошибку:

 incomplete type 'contains<double*, void (A::*)(int, double*)>' used in nested name specifier

Как я понял, типы:

void(int, double*)
void(*)(int, double*)
void(A::*)(int, double*)

Во втором случае я могу использовать std::remove_pointer_t, но как я могу удалить (A::*) из сигнатуры функции в третьем случае?

1 Ответ

0 голосов
/ 28 июня 2018

Вы можете добавить другие специализации:

template<typename, typename> struct contains;

template<typename T, typename R, typename... Ts>
struct contains<T, R(Ts...)>
{
    static constexpr bool result = std::disjunction_v<std::is_same<T, Ts>...>;
};

template<typename T, typename R, typename... Ts>
struct contains<T, R (*)(Ts...)> : contains<T, R(Ts...)>
{
};

template<typename T, typename C, typename R, typename... Ts>
struct contains<T, R (C::*)(Ts...)> : contains<T, R(Ts...)>
{
};

// And even more for R (C::*) (Ts... ...) const volatile &&

А потом

int main ()
{
    std::cout << std::boolalpha << contains<double*, decltype(foo)>::result;
    std::cout << std::boolalpha << contains<double*, decltype(&A::staticFoo)>::result;
    std::cout << std::boolalpha << contains<double*, decltype(&A::foo)>::result;
}
...