You can use the following code:
#include <type_traits> template<class T> void f_impl(T*, T*) { std::cout << typeid(T).name() << "\n"; } template<class T, class U> void f(T l, U r) { static_assert((std::is_same<T, U>::value && std::is_pointer<T>::value) || (std::is_same<T, std::nullptr_t>::value && std::is_pointer<U>::value) || // First non-null (std::is_same<U, std::nullptr_t>::value && std::is_pointer<T>::value) // Second non-null , ""); using P = typename std::conditional<std::is_same<T, std::nullptr_t>::value, U, T>::type; f_impl<typename std::remove_pointer<P>::type>(l, r); } int main() { int i; f(&i, nullptr); f(nullptr, &i); // f(i, nullptr); // won't compile - non-pointer f(&i, &i); double d; // f(&i, &d); // - won't compile }
These version tests will allow f to be called with one nullptr (but not both) or with two pointers to the same type. With C ++ 14, you can also use things like std::conditional_t , std::remove_pointer_t and std::is_null_pointer to remove some biolerplate.
source share