Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::is_member_function_pointer does not compile if false

What I am looking for: I have a templated class and want to call a function if the class has the wanted function, something like:

template<class T> do_something() {
    if constexpr (std::is_member_function_pointer<decltype(&T::x)>::value) {
        this->_t->x(); // _t is type of T*
    }
}

What happens: The compiler does not compile if T does not bring the function. Small example:

#include <type_traits>
#include <iostream>

class Foo {
public:
    void x() { }
};

class Bar { };

int main() {
    std::cout << "Foo = " << std::is_member_function_pointer<decltype(&Foo::x)>::value << std::endl;
    std::cout << "Bar = " << std::is_member_function_pointer<decltype(&Bar::x)>::value << std::endl;
    return 0;
}

Compiler says:

is_member_function_pointer.cpp:17:69: error: no member named 'x' in 'Bar'; did you mean 'Foo::x'?
    std::cout << "Bar = " << std::is_member_function_pointer<decltype(&Bar::x)>::value << std::endl;

So, what is the std::is_member_function_pointer for, when I can not use it in an if constexpr? If I just use this->_t->x() the compiler will fail, too, for sure.

like image 495
jagemue Avatar asked Mar 14 '19 11:03

jagemue


1 Answers

is_member_function_pointer doesn't detect the existence of an entity T::x, it assumes it does and returns whether or not it is a member function pointer.

If you want to detect whether it exists or not, you can use the detection idiom. Example:

#include <experimental/type_traits>

template<class T>
using has_x = decltype(&T::x);

template<class T> void do_something(T t) {
    if constexpr (std::experimental::is_detected<has_x, T>::value) {
        t.x(); 
    }
}

struct Foo {
    void x() { }
};

struct Bar { };

int main() {
    do_something(Foo{});
    do_something(Bar{});
}

live example on godbolt.org


I have written an article on the general problem of checking the validity of an expression in different C++ Standard versions:

"checking expression validity in-place with C++17"

like image 59
Vittorio Romeo Avatar answered Nov 20 '22 20:11

Vittorio Romeo