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.
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With