Finding T::substr is not the same as looking for a member function called substr . Gcc.godbolt.org example
You can check if a member function exists using std::declval<T>() and using decltype to get the return type of the member function.
If a member function exists, decltype(...) will be a well-formed expression and will not call SFINAE, so static_assert will work correctly.
#include <string> #include <type_traits> #include <utility> template <typename...> using void_t = void; template <typename, typename = void> class HasMember_substr : public std::false_type {}; template <typename T> class HasMember_substr<T, void_t< decltype(std::declval<T>().substr(1, 1))> > : public std::true_type {}; static_assert(HasMember_substr<std::string>::value, ""); int main() { return 0; }
Note that decltype(std::declval<T>().substr(1, 1)) checks if T a substr member that can be called with arguments 1, 1 . (This is not guaranteed as a member function; it can also be an element of a functor data.)
As AndyG said in the comments, another possible approach uses decltype to "check" the type of a member function pointer.
Example:
HasMember_substr<T, void_t< decltype(&T::substr)>
Please note that this will not work if substr overloaded, and does not guarantee operation with any type in the standard library .
Vittorio romeo
source share