#include <cstdint>
#include <iostream> // for test
#include <type_traits>
#include <utility>
template<class T>
class pointer
{
using this_type = pointer<T>;
T* _ptr;
public:
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
using difference_type = std::ptrdiff_t;
pointer() noexcept : _ptr() {}
pointer(T* p) noexcept : _ptr(p) {}
T* get() const noexcept { return _ptr; }
T* operator->() const noexcept { return _ptr; }
reference operator*() const noexcept { return (*_ptr); }
// この場合の添え字演算子は関節参照演算子のシンタックスシュガー
reference operator[](std::ptrdiff_t diff) { return *(_ptr + diff); }
const_reference operator[](std::ptrdiff_t diff) const { return *(_ptr + diff); }
reference operator++() { ++_ptr; return (*this); }
reference operator--() { --_ptr; return (*this); }
value_type operator++(int) { this_type temp(*this); ++*this; return temp; }
value_type operator--(int) { this_type temp(*this); --*this; return temp; }
explicit operator bool() const noexcept { return _ptr; }
bool operator!() const noexcept { return !static_cast<bool>(*this); }
template<class U,
std::enable_if_t<std::is_member_function_pointer<U>::value, std::nullptr_t> = nullptr>
auto operator->*(U u) const noexcept
{
return [u, this](auto... args)
{ // lambda
return (_ptr->*u)(std::forward<decltype(args)>(args)...);
};
}
template<class U,
std::enable_if_t<std::is_member_object_pointer<U>::value, std::nullptr_t> = nullptr>
auto& operator->*(U u) const noexcept
{
return _ptr->*u;
}
reference operator+=(difference_type diff)
{ _ptr += diff; return (*this); }
reference operator-=(difference_type diff)
{ _ptr -= diff; return (*this); }
};
template<class T, class U>
static inline bool operator==(const pointer<T>& p1, const pointer<U>& p2) noexcept
{
return p1.get() == p2.get();
}
// この減算は例の厄介なやつ。
template<class T, class U>
static inline auto operator-(const pointer<T>& p1, const pointer<U>& p2)
->typename pointer<T>::difference_type
{
return typename pointer<T>::difference_type(p1.get() - p2.get());
}
struct something
{
void great_function() const { std::cout <<"I am great." << std::endl; }
int great_n = 0;
};
int main()
{
something s;
pointer<something> ps(&s);
ps->great_function();
auto pgreat_func = &something::great_function;
(ps->*pgreat_func)();
auto pgreat_n = &something::great_n;
ps->*pgreat_n = 10;
int n = ps->*pgreat_n;
std::cout << n << std::endl;
}