Skip to content

Instantly share code, notes, and snippets.

@eyalroz
Created November 8, 2021 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eyalroz/17ccfa26fb63c9385c1d2c4f943e59c9 to your computer and use it in GitHub Desktop.
Save eyalroz/17ccfa26fb63c9385c1d2c4f943e59c9 to your computer and use it in GitHub Desktop.
A generic proxy class for replacing getters and setters
#include <type_traits>
#include <utility>
#ifndef CONSTEXPR_SINCE_CPP14
# if __cplusplus >= 201402L
# define CONSTEXPR_SINCE_CPP14 constexpr
# else
# define CONSTEXPR_SINCE_CPP14
# endif
#endif
template <typename Handle, typename Getter, typename Setter>
class proxy {
public:
using getter_return_type = decltype(std::declval<Getter>()(std::declval<Handle>()) );
// Note: We assume the getter does not allow modifying the value. If it
// does - you don't need the proxy in the first place. But _asserting_ this
// is difficult. For example, suppose the getter returns an int*. Is the
// "actual" value an int, or an int*? We can't know that without introducing
// yet another type parameter.
using value_type = typename std::remove_reference<typename std::remove_cv<getter_return_type>::type>::type;
CONSTEXPR_SINCE_CPP14
operator getter_return_type() const noexcept(noexcept(getter_))
{ return getter_(handle_); }
CONSTEXPR_SINCE_CPP14 proxy&
operator=(const value_type& x) noexcept(noexcept(setter_))
{ setter_(handle_, x); return *this; }
CONSTEXPR_SINCE_CPP14 proxy&
operator=(value_type&& x) noexcept(noexcept(setter_))
{ setter_(handle_, std::move(x)); return *this; }
CONSTEXPR_SINCE_CPP14
proxy(Handle handle, const Getter& getter, const Setter& setter) noexcept
: handle_(handle), getter_(getter), setter_(setter) { }
protected:
const Handle handle_;
// Note: The handle is constant, not the referred-to element. So, _don't_
// use a `T&` as your Handle, or you'll be in trouble
const Getter& getter_;
const Setter& setter_;
// Note: Attempts to use just plain Getter and Setter as the types here
// don't work when Getter/Setter are function types
};
// Allows for template argument deduction during "construction" - before C++17
template <typename Handle, typename Getter, typename Setter>
CONSTEXPR_SINCE_CPP14 proxy<Handle, Getter, Setter>
make_proxy(const Handle& handle, const Getter& getter, const Setter& setter) noexcept
{
return proxy<Handle, Getter, Setter>(handle, getter, setter);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment