#include <iostream>
#include <type_traits>
struct Coordinate
{
double x;
double y;
};
template <typename T> class val
{
public:
val(const T& t) : t(t) {}
val(const val&) = default;
val& operator = (const val&) = delete;
const T* operator->() const { return &t; }
const T& get() const { return t; }
T* operator->() { return &t; }
T& get() { return t; }
private:
T t;
};
template <typename T> class var
{
public:
var(const T& t) : t(t) {}
var(const var&) = default;
var& operator = (const var&) = default;
var& operator = (const T&) { this->t = t; return *this; };
const T* operator->() const { return &t; }
const T& get() const { return t; }
T* operator->() { return &t; }
T& get() { return t; }
private:
std::remove_const_t<T> t;
};
int main()
{
val<const Coordinate> immutable_val({42, 51});
val<Coordinate> mutable_val({42, 51});
var<const Coordinate> immutable_var({42, 51});
var<Coordinate> mutable_var({42, 51});
//immutable_val->x = 42; // error: cannot assign to return value because function 'operator->' returns a const value
mutable_val->x = 42;
//immutable_var->x = 42; // error: cannot assign to return value because function 'operator->' returns a const value
mutable_var->x = 42;
//immutable_val = {42, 42}; // error: overload resolution selected deleted operator '='
//mutable_val = {42, 42}; // error: overload resolution selected deleted operator '='
immutable_var = {42, 42};
mutable_var = {42, 42};
//mutable_val = mutable_val; // error: overload resolution selected deleted operator '='
//immutable_val = immutable_val; // error: overload resolution selected deleted operator '='
immutable_var = immutable_var;
mutable_var = mutable_var;
}