How can I check at compile-time whether or not an arbitrary type can be used with std::pointer_traits? I had hoped a simple SFINAE solution might work:
template <typename T, typename = void>
struct pointer_traits_ready : std::false_type {};
template <typename T>
struct pointer_traits_ready<
T,
std::void_t<typename std::pointer_traits<T>::element_type>
> : std::true_type {};
static_assert(!pointer_traits_ready<int>::value,"");
...but this invokes a static assert from within the standard library (ptr_traits.h). Obviously std::is_pointer doesn't accommodate smart pointers.
You can't. From [pointer.traits.types]:
using element_type = see below ;Type:
Ptr::element_typeif the qualified-idPtr::element_typeis valid and denotes a type (14.8.2); otherwise,TifPtris a class template instantiation of the formSomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the specialization is ill-formed.
In order to be SFINAE-friendly, we would need pointer_traits<Foo> to simply lack a type alias named element_type. The problem is, element_type is specified as being ill-formed - not absent. So you simply cannot use pointer_traits as a detector for whether or not something can be used as a pointer type.
Even if you wrote your own type that was a SFINAE-friendly version of that specification, you wouldn't be able to catch user specializations of pointer_traits for their own type. Sad panda.
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