Why do you need SFINAE in `std::add_pointer_t`?

Viewed 112

I've been hacking around the standard library lately, since I need to implement a subset of it (mostly template stuff) for a system which doesn't have an stdlib implementation.

I came across this "possible implementation", in cppreference:

namespace detail {
 
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
 
template <class T>
auto try_add_pointer(int) -> type_identity<typename std::remove_reference<T>::type*>;
template <class T>
auto try_add_pointer(...) -> type_identity<T>;
 
} // namespace detail
 
template <class T>
struct add_pointer : decltype(detail::try_add_pointer<T>(0)) {};

and I've been wondering why do you need SFINAE here. Isn't this:

template< class T >
struct add_pointer {
    typedef typename std::remove_reference<T>::type* type;
};

enough? which instantiation takes the second case of try_add_pointer? I tried to think about it but couldn't think about any such case.

1 Answers

I'm not sure if this is the only bad case, but your implementation fails for so-called "abominable function types":

add_pointer<void() const>::type // hard error instead of void() const
Related