For member detection in C++14 I used code based on the example here, but it does no seem to work.
A complete example:
#include <string>
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<typename T::substr>> : public std::true_type {};
template <typename, typename = void> class HasMember_fff : public std::false_type {};
template <typename T> class HasMember_fff<T, void_t<typename T::fff>> : public std::true_type {};
static_assert(HasMember_substr<std::string>::value, "");
static_assert(!HasMember_fff<std::string>::value, "");
int main() { return 0; }
Compiled using clang++ --std=c++14 test.cpp
on OS X, compiler version (clang++ --version
): Apple LLVM version 7.0.2 (clang-700.1.81)
The second assert succeeds, but the first fails. Why? I have also tried using decltype(T::substr)
instead of typename T::subset
, with the same result.
Looking for 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 by using std::declval<T>()
and using decltype to get the return type of the member function.
If the member function exists, decltype(...)
will be a well-formed expression and will not trigger SFINAE - therefore the the 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 whether T
has a substr
member that can be called with arguments 1, 1
. (This is not guaranteed to be a member function, it could also be a functor data member, for example.)
As said by AndyG in the comments, another possible approach is using decltype
to "validate" the type of a member function pointer.
Example:
HasMember_substr<T, void_t< decltype(&T::substr)>
Note that this will not work if the name substr
is overloaded, and it is not guaranteed to work with any type in the standard library.
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