#include <iostream>
#include <type_traits>
#include <vector>

template <typename T>
auto is_iterator_impl(T* it)
-> decltype(**it, ++(*it), (*it) == (*it), std::true_type());

template <typename T>
auto is_iterator_impl(...) -> std::false_type;

template <typename T>
using is_an_iterator = decltype(is_iterator_impl<T>(0));

template <class R>
std::enable_if_t<!is_an_iterator<R>::value, int>
make_ref(R& res) {
    std::cout << "Not an iterator\n";
}

template <class R>
std::enable_if_t<is_an_iterator<R>::value && !std::is_pointer<R>::value>
make_ref(R& res) {
    std::cout << "An iterator\n";
}

template <class R>
std::enable_if_t<std::is_pointer<R>::value>
make_ref(R& res) {
    std::cout << "A pointer\n";
}

int main() {
	int i = 42;
	std::vector<int> v{4, 8, 15, 16, 23, 42};
	auto it = v.begin();
	const char*	s = "hello";
	make_ref(i);
	make_ref(it);
	make_ref(s);
}